算法模板の字符串处理
1、AC自动机
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void buildTrie(Node *root, char *str){ 2 Node *p = root; 3 for(int i = 0; str[i]; ++i){ 4 int index = str[i] - '0'; 5 if(!p->next[index]) p->next[index] = new Node(ecnt++); 6 p = p->next[index]; 7 } 8 p->flag = true; 9 } 10 11 void makeFair(Node *root){ 12 queue<Node*> que; que.push(root); 13 while(!que.empty()){ 14 Node *tmp = que.front(); que.pop(); 15 for(int i = 0; i < 10; ++i){ 16 if(!tmp->next[i]) continue; 17 if(tmp == root) tmp->next[i]->fail = root; 18 else{ 19 Node *p = tmp->fail; 20 while(p){ 21 if(p->next[i]){ 22 tmp->next[i]->fail = p->next[i]; 23 break; 24 } 25 p = p->fail; 26 } 27 if(!p) tmp->next[i]->fail = root; 28 } 29 if(tmp->next[i]->fail->flag) tmp->next[i]->flag = true; 30 else que.push(tmp->next[i]); 31 } 32 } 33 root->fail = root; 34 }
2、后缀自动机(HDU 1403)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 6 const int MAXN = 100000 + 10; 7 char buf[MAXN]; 8 struct State { 9 State *par, *go[26]; 10 int val;/* 11 State() : 12 par(0), val(0) { 13 memset(go, 0, sizeof go); 14 }*/ 15 }*root, *last; 16 State statePool[MAXN * 2], *cur; 17 18 void init() { 19 memset(statePool, 0, 2 * strlen(buf) * sizeof(State)); 20 cur = statePool; 21 root = last = cur++; 22 } 23 24 void extend(int w) { 25 State *p = last, *np = cur++; 26 np->val = p->val + 1; 27 while (p && !p->go[w]) 28 p->go[w] = np, p = p->par; 29 if (!p) np->par = root; 30 else { 31 State*q = p->go[w]; 32 if (p->val + 1 == q->val) np->par = q; 33 else { 34 State *nq = cur++; 35 memcpy(nq->go, q->go, sizeof q->go); 36 nq->val = p->val + 1; 37 nq->par = q->par; 38 q->par = nq; 39 np->par = nq; 40 while (p && p->go[w] == q) 41 p->go[w] = nq, p = p->par; 42 } 43 } 44 last = np; 45 } 46 47 int main() { 48 char *pt; 49 while(scanf("%s", buf) != EOF) { 50 init(); 51 for (pt = buf; *pt; ++pt) 52 extend(*pt - 'a'); 53 scanf("%s", buf); 54 State *t = root; 55 int l = 0, ans = 0; 56 for (pt = buf; *pt; ++pt) { 57 int w = *pt - 'a'; 58 if (t->go[w]) { 59 t = t->go[w]; 60 ++l; 61 } else { 62 while (t && !t->go[w]) t = t->par; 63 if (!t) l = 0, t = root; 64 else { 65 l = t->val + 1; 66 t = t->go[w]; 67 } 68 } 69 ans = max(ans, l); 70 } 71 printf("%d\n", ans); 72 } 73 return 0; 74 }
3、后缀数组//字符串末尾要手动添加一个最小字符(比如0)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 char s[MAXN]; 2 int sa[MAXN], height[MAXN], rank[MAXN], c[MAXN], tmp[MAXN]; 3 int n; 4 5 void makesa(int m) { 6 memset(c, 0, m * sizeof(int)); 7 for(int i = 0; i < n; ++i) ++c[rank[i] = s[i]]; 8 for(int i = 1; i < m; ++i) c[i] += c[i - 1]; 9 for(int i = 0; i < n; ++i) sa[--c[rank[i]]] = i; 10 for(int k = 1; k < n; k <<= 1) { 11 for(int i = 0; i < n; ++i) { 12 int j = sa[i] - k; 13 if(j < 0) j += n; 14 tmp[c[rank[j]]++] = j; 15 } 16 int j = c[0] = sa[tmp[0]] = 0; 17 for(int i = 1; i < n; ++i) { 18 if(rank[tmp[i]] != rank[tmp[i - 1]] || rank[tmp[i] + k] != rank[tmp[i - 1] + k]) 19 c[++j] = i; 20 sa[tmp[i]] = j; 21 } 22 memcpy(rank, sa, n * sizeof(int)); 23 memcpy(sa, tmp, n * sizeof(int)); 24 } 25 } 26 27 void calheight() { 28 for(int i = 0, k = 0; i < n; height[rank[i++]] = k) { 29 if(k > 0) --k; 30 int j = sa[rank[i] - 1]; 31 while(s[i + k] == s[j + k]) ++k; 32 } 33 } 34 35 int logn[MAXN]; 36 int best[20][MAXN]; 37 38 void initRMQ() { 39 logn[0] = -1; 40 for(int i = 1; i <= n; ++i) 41 logn[i] = (i & (i - 1)) == 0 ? logn[i - 1] + 1 : logn[i - 1]; 42 for(int i = 1; i <= n; ++i) best[0][i] = height[i]; 43 for(int i = 1; i <= logn[n]; ++i) { 44 int ed = n - (1 << i) + 1; 45 for(int j = 1; j <= ed; ++j) 46 best[i][j] = min(best[i - 1][j], best[i - 1][j + (1 << (i - 1))]); 47 } 48 } 49 50 int lcp(int a, int b) { 51 a = rank[a], b = rank[b]; 52 if(a > b) swap(a, b); 53 ++a; 54 int t = logn[b - a + 1]; 55 return min(best[t][a], best[t][b - (1 << t) + 1]); 56 }
4、Manacher(Update:2014年11月13日)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void manacher() { 2 int mx = 0, id; 3 for(int i = 1; i < n; ++i) { 4 if(mx > i) p[i] = min(p[2 * id - i], mx - i); 5 else p[i] = 1; 6 while(s[i + p[i]] == s[i - p[i]]) ++p[i]; 7 if(i + p[i] > mx) { 8 id = i; 9 mx = i + p[i]; 10 } 11 } 12 } 13 14 void print() { 15 int id = 0; 16 for(int i = 1; i < n; ++i) 17 if(p[i] > p[id]) id = i; 18 int l = (id - p[id] + 1) / 2, r = l + p[id] - 1; 19 for(int i = l; i < r; ++i) putchar(str[i]);// 范围[l, r) 20 puts(""); 21 } 22 23 int main() {//两倍数组大小 24 scanf("%s", str); 25 s[n++] = '$', s[n++] = '#'; 26 for(int i = 0; str[i]; ++i) { 27 s[n++] = str[i]; 28 s[n++] = '#'; 29 } 30 s[n] = 0; 31 manacher(); 32 print(); 33 }