2014-12-18 00:22:30
思路:這題目好想不好做- -、(事實上能想到就不容易了)
看了題解的思路....然後自己敲的。
考慮:把所有正串都加進一棵trie,然後用每個串的逆串去跑trie,此時會出現兩種情況:
(1)匹配完成,那麼就說明存在乙個正串的字首是這個逆串。如果剩餘的逆串回文,那麼能形成回文。
(2)匹配失敗,trie未結束,說明不能構成回文。
(3)trie已經跑到葉子節點,匹配未結束,那麼如果正串剩餘部分回文,那麼能形成回文。
用擴充套件kmp處理出乙個串的每個字尾是不是回文串,方法是用該串和其逆串僅用擴充套件kmp匹配,如果ex[i]=(從i到末尾的長度),那麼說明從i到末尾的字尾是回文的。
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include8 #include 9 #include 10 #include 11 #include 12
using
namespace
std;
13#define lp (p << 1)
14#define rp (p << 1|1)
15#define getmid(l,r) (l + (r - l) / 2)
16#define mp(a,b) make_pair(a,b)
17 typedef long
long
ll;18 typedef unsigned long
long
ull;
19const
int inf = 1
<< 30;20
const
int maxn = 2000010;21
22int
n,tot,tcnt;
23int
ex[maxn],next[maxn],len[maxn];
24char
tmp[maxn],s[maxn],rtmp[maxn];
25ll ans;
26struct
trie*root;
3132
trie t[maxn];
3334
void ex_kmp(char *s,char *rs,int
m)47
}48 k = 0;49
while(k < m && rs[k] == s[k]) k++;
50 ex[0] =k;
51 k = 0; //
因為0位置已經算過
52for(int i = 1; i < m; ++i)59}
60}6162
void insert_trie(char *s,int
m)73 p = p ->next[id];
74 p -> v += (i + 1
< m && ex[i + 1] == m - i - 1) ? 1 : 0;75
}76 p -> flag++;77}
7879
void find(char *s,int
m)87 ans += p ->v;88}
8990
intmain()
103 tot = 0
;104 ans = 0
;105
for(int i = 0; i < n; ++i)
111 printf("
%i64d\n
",ans);
112return0;
113 }
poj3376 字典樹 擴充套件kmp
kuangbin專題十六字最後一發 題意 n個字串,每個字串長度為l,將字串兩兩自由組合一共有 n n種方案 判斷其中組合之後為回文串的字元有多少個.做法 首先由兩個字串a,b.要使它們能組成回文串有三種情況 1.alen blen 時 a是b的反串字首,且b的剩餘部分可以認為是字尾是回文串 2.a...
poj 3376 擴充套件kmp求回文加字典樹
回文串的性質 它的每個字首都是它的字尾,正序串和反序串kmp得字尾回文串的各個長度 反序串和正序串kmp得字首回文串的各個長度 kmp求出所有串的字首回文串和字尾回文串然後把正序串依次存入字典樹,然後列舉反序串進行查詢與字典樹上的串進行匹配得出結果。坑了兩個晚上 include include in...
POJ 2752 (擴充套件kmp)
給你乙個字串,對於它的每乙個字首,如果同時是它的字尾的話,那麼輸出這個字首的位置。擴充套件kmp求一下next陣列,然後掃一遍每個位置,如果這個位置的next值 也就是這個位置的字尾和字首的最大匹配長度 是等於字尾長度的話,也就是說這個位置的字尾同時也是它的字首的話,那麼這個位置就是乙個答案。inc...