這題過得很艱辛啊。最早在去年網路賽時就見到這題了,當時是不會。前段時間好好學了一下字尾陣列,昨天再來看這題,就知道顯然是字尾陣列的應用了。
我知道解這道題肯定是類似於用字尾陣列求字串所有不同子串個數的思路。但一開始想走捷徑,想法是先把所有的b連起來,再連上a,並通過在a後面加上一些特定字元的方法,使在sa中a的子串都排在b的後面,這樣只要倒著統計一遍就行了。**打完後才想明白這是完全行不通的。正確思路只能是分兩次做,一次是只把所有的b連起來,求出所有不同子串數sumb,第二次是把a也連上,求出所有不同子串數sumab,最後結果就是sumab - sumb。
具體實現過程也有好多需要注意的,比如,為了方便除掉包含分隔字元的子串數,需要使每個分隔字元都不一樣,由於所有的b串最多有100000個,所以沒法用字元型別處理了,我是用的整型陣列代替。還有就是最後結果要用long long型別,等等。
/** hdu4416/win.cpp
* created on: 2013-5-21
* author : ben */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
typedef
long
long
ll;const
int maxn = 330000
;int *s;
intsa[maxn], height[maxn], rank[maxn];
inttmp[maxn], top[maxn];
intn;
void
makesa()
sa[tmp[top[
0] = 0]] = j = 0
;
for (i = 1; i < n; i++)
memcpy(rank, sa, n * sizeof(int
)); memcpy(sa, tmp, n * sizeof(int
));
if (j >= n - 1
)
break
; }
}void
lcp()
int get_str(int *str)
}int i = 0
;
while (c > '')
str[i] = 0
;
returni;}
intstr[maxn];
intlenarr[maxn];
intmain()
n = p -str;
str[n - 1] = 0
;
//a、b連起來求字尾陣列
s =str;
makesa();
lcp();
//統計不同子串個數
sumab = 0
;
for(int i = 1; i < n; i++)
//減掉帶#的子串數
temp = n - 1
;
for(int i = 0; i < n; i++)
//單獨求b的字尾陣列
s = str + lenarr[0] + 1
; n = n - lenarr[0] - 1
; makesa();
lcp();
//統計不同子串個數
sumb = 0
;
for(int i = 1; i < n; i++)
//減掉帶#的子串數
temp = n - 1
;
for(int i = 1; i < n; i++)
printf(
"case %d: %i64d\n
", t, sumab -sumb);
}return0;
}
字尾自動機1003 HDU 4416
題意 給乙個模式串,然後給n個匹配串,問模式串裡有多少個子串是n個匹配串裡都不存在的 思路 就是注意乙個性質就行了 假設當前節點的len 6,當前節點的pre節點len 2 這個節點接收的狀態就是以當前節點為最後乙個字元的字尾的長度是3 6裡 比如當前節點的最長字尾是abcabb sam.len 6...
字尾陣列 HDU 4436
做法 首先應用求不同子串的演算法,自然想到字尾陣列,然後就是要統計以非 0 開始的字尾。考慮字尾 akak 1ak 2.an tmp 0 ak 0 tmp i tmp i 1 10 ai 0 sum i sum i 1 tmp i 那麼 以 am開始的字首和就是 sum n sum m 1 tmp ...
hdu 3518 字尾陣列
晚飯前寫的 一直wa,一直想不通,後來寫程式對拍了,一百組資料中錯了一組,然後還是想不通為什麼的,然後的然後看了別人的 然後瞬間知道自己為什麼wa!還是對字尾陣列了解的不夠,自己預設的是sa中排在前面的然後在字串陣列中下標也是在前面的,然後就沒有挨個比較相同長度中的取最大值和最小值,所以wa的可憐啊...