time limit: 20 sec memory limit: 256 mb給定兩個字串,求出在兩個字串中各取出乙個子串使得這兩個子串相同的方案數。兩個方案不同當且僅當這兩
個子串中有乙個位置不同。
兩行,兩個字串s1,s2,長度分別為n1,n2。1 <=n1, n2<= 200000,字串中只有小寫字母
輸出乙個整數表示答案
aabb
bbaa
10我字尾自動機入門啦啦啦~
這道題有兩種做法:
做法一:你可以把兩個串分別建乙個字尾自動機,然後再把兩個串用 # 連線起來再建乙個字尾自動機。每個自動機都可以得到有多少個不同的子串。所以答案等於前面兩個小的自動機的答案減去後面這個大的自動機的答案。
我寫的是做法二:
就是說你先用第乙個串建乙個字尾自動機,然後拿第二個串去跑 。(就是匹配不到了該跳 fail 就跳,和 ac 自動機差不多的那種。)
然後你記錄一下每個節點被進入了多少次。再記錄一下你當前匹配的長度。注意最後統計的時候是直接統計的匹配長度是 【l,r】 的,所以進每個節點時先減去不合法的。這樣最後統計答案才正確。並且你跳鏈的時候匹配的長度要和你當前匹配長度取min。因為每個節點的管理區間是有限的,所以只能匹配你長度在區間裡的串。
#includeusing namespace std;
const int maxn = 2e5 + 6;
struct lplnode[maxn << 1];
char s[maxn];
int cnt = 1, last = 1, pr[maxn], rk[maxn << 1];
long long ans;
void insert(int t, int l)
if(!i) int now = node[i].son[t];
if(node[now].len == node[i].len + 1)
int nw = ++cnt; for(int j = i; j && node[j].son[t] == now; j = node[j].parent) node[j].son[t] = nw;
node[nw] = node[now]; node[nw].len = node[i].len + 1; node[nw].num = 0;
node[now].parent = nw; node[last].parent = nw;
}void match(int u, int pos, int l)
int main()
for(int i = cnt; i >= 1; --i) node[node[rk[i]].parent].num += node[rk[i]].num;
scanf("%s", s + 1); match(1, 1, 0);
for(int i = cnt; i >= 1; --i)
printf("%lld", ans);
return 0;
}
bzoj4566 HAOI2016 找相同字元
time limit 20 sec memory limit 256 mb submit 113 solved 64 submit status discuss description 給定兩個字串,求出在兩個字串中各取出乙個子串使得這兩個子串相同的方案數。兩個方案不同當且僅當這兩 個子串中有乙個位...
BZOJ4566 Haoi2016 找相同字元
bzoj4566 haoi2016 找相同字元 給定兩個字串,求出在兩個字串中各取出乙個子串使得這兩個子串相同的方案數。兩個方案不同當且僅當這兩個子串中有乙個位置不同。兩行,兩個字串s1,s2,長度分別為n1,n2。1 n1,n2 200000,字串中只有小寫字母 輸出乙個整數表示答案 aabb b...
BZOJ4566 HAOI2016 找相同字元
bzoj luogu 首先把兩個串拼在一起跑字尾陣列。中間插入乙個沒有出現過的字元。求完字尾陣列之後考慮 o n 2 暴力統計 列舉前乙個串和後乙個串的兩個位置,ans lcp i,j 現在改為把一共 2n 個字尾按 rank 順序插入,每插入乙個字尾,統計與其不在同乙個串裡的字尾的貢獻。發現可以單...