kuangbin專題十六字最後一發
題意:n個字串,每個字串長度為l,將字串兩兩自由組合一共有(n * n種方案)判斷其中組合之後為回文串的字元有多少個.
做法:首先由兩個字串a,b.要使它們能組成回文串有三種情況
1.alen < blen 時
a是b的反串字首,且b的剩餘部分可以認為是字尾是回文串
2.alen > blen
b的反串是a的字首,且a的字尾是回文串
3.alen == blen
b是a的反串
現將所有字串建立在字典樹中。然後求s和s的反串的字尾中是回文串的位置,也就是說從哪個位置開始一直到最後是回文串實現就是(i + extend[i] == n,以正串為例,反串的首位就是正串的最後一位相等 )。用字典樹中的引數huiwen記錄從該字母開始回文串的個數,注意回文記錄的只是以正串為字尾的個數
另外:因為只給了字串的總長度,所以,只開一維的字串陣列,每次接著上次字串結束的位置開始即可。為了方便,記錄字串開始的位置,和結束的位置
#include#include#include#include#includeusing namespace std;
const int maxn=2000007;
long long ans = 0;
bool flag[2][maxn];
int nexta[maxn];
int extend[maxn];
void ekmp(char s,char t,int bg,int ed,int sign)//s主串,t模式串
nexta[bg + 1] = k;
k = bg + 1;
int p,l,j;
for(int i = 2 + bg; i < ed; i ++)
else
nexta[i] = j;
k = i;}}
for(k = 0; k+ bg < ed && s[k+bg] == t[k+bg]; k ++ )
extend[bg] = k;
k = bg;
for(int i = bg + 1; i < ed; i ++)
else
extend[i] = j;
k = i;}}
for(int i = bg; i < ed; i ++)
}}struct node
f[2000006];
void init(int a)//新增函式
int cnt = 1;
void build(char a,int bg,int ed)
if(f[p].nexta[t] == -1)
p = f[p].nexta[t];
}f[p].countx ++;//單詞相同的個數。hud1251則是字首相同的個數
}void findx(char a,int bg,int ed)
}if(k != -1)//反串比正串短的情況,要加上正串後面都是回文串的情況
//注意因為是要匹配n * n次,保證不重不漏。
return;
}char s[maxn],ins[maxn];
int bg[maxn],ed[maxn];
int main()
bg[t] = l;
ed[t] = l + n;
l += n;
ekmp(s,ins,bg[t],ed[t],0);
ekmp(ins,s,bg[t],ed[t],1);
build(s,bg[t],ed[t]);
}for(int i = 0; i < t; i ++)
cout<
poj 3376 擴充套件kmp求回文加字典樹
回文串的性質 它的每個字首都是它的字尾,正序串和反序串kmp得字尾回文串的各個長度 反序串和正序串kmp得字首回文串的各個長度 kmp求出所有串的字首回文串和字尾回文串然後把正序串依次存入字典樹,然後列舉反序串進行查詢與字典樹上的串進行匹配得出結果。坑了兩個晚上 include include in...
Poj 3376(擴充套件KMP,Trie)
2014 12 18 00 22 30 思路 這題目好想不好做 事實上能想到就不容易了 看了題解的思路.然後自己敲的。考慮 把所有正串都加進一棵trie,然後用每個串的逆串去跑trie,此時會出現兩種情況 1 匹配完成,那麼就說明存在乙個正串的字首是這個逆串。如果剩餘的逆串回文,那麼能形成回文。2 ...
字典樹 與 01字典樹
字典樹可以降低空間複雜度 01字典樹可以降低時間複雜度。字典樹 又稱單詞查詢樹,trie樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計,排序和儲存大量的字串 但不僅限於字串 所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是 利用字串的公共字首來減少查詢時間,最大限度地減少無謂的字串比較...