zoukankan      html  css  js  c++  java
  • 字符串专题

    Flag:

    1. SA精通应用

    2. KMP/Manacher 模板熟练((color{red}{ ext{GET}})

    3. Trie/AC自动机 模板熟练。

    4. 扩展KMP/字符串最小表示法(咕咕咕) 模板熟练

    KMP模板:

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int ls, lt, nxt[1000005];
    char T[1000005], S[1000005];
    int main(){
    	scanf("%s", S + 1);
    	scanf("%s", T + 1);
    	ls = strlen(S + 1);
    	lt = strlen(T + 1);
    	nxt[1] = 0;
    	for(int i = 2, j = 0; i <= lt; i++){
    		while(j != 0 && T[i] != T[j + 1])	j = nxt[j];
    		if(T[i] == T[j + 1]) j++;
    		nxt[i] = j;
    	}
    	for(int i = 1, j = 0; i <= ls; i++){
    		while(j == lt || (j != 0 && S[i] != T[j + 1])) j = nxt[j];
    		if(S[i] == T[j + 1]) j++;
    		if(j == lt) printf("%d
    ", i - lt + 1);
    	}
    	for(int i = 1; i <= lt; i++) printf("%d ", nxt[i]);
    	return 0;
    }
    

    manacher模板:

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int ls, P[23000100], ans;
    char S[23000100];
    int main(){
        S[0] = '$';
        char ch = getchar();
        while(ch >= 'a' && ch <= 'z') S[++ls] = '#', S[++ls] = ch, ch = getchar();
        S[++ls] = '#'; S[++ls] = '^';
        for(int i = 1, R = 0 , now = 0; i <= ls; i++){
            if(i <= R) P[i] = min(P[now + now - i], R - i);
            else P[i] = 0;
            while(S[i + P[i] + 1] == S[i - P[i] -1]) P[i]++;
            if(P[i] + i > R) R = P[i] + i, now = i;
            ans = max(ans, P[i]);
        }
        cout << ans << endl;
        return 0;
    }
    

    Trie模板:

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    struct trie{
    	struct node{
    		int ch[26], cnt, bj;
    	}t[510005];
    	int tot, rt;
    	int NEW(){
    		return ++tot;
    	}
    	void change(char *S, int ls){
    		int now = (rt = rt == 0 ? NEW() : rt);
    		for(int i = 1; i <= ls; i++){
    			int z = S[i] - 'a';
    			if(t[now].ch[z] == 0)
    				t[now].ch[z] = NEW();
    			now = t[now].ch[z];
    		}
    		t[now].cnt++;
    	}
    	int query(char *S, int ls){
    		int now = (rt = rt == 0 ? NEW() : rt);
    		for(int i = 1; i <= ls; i++){
    			int z = S[i] - 'a';
    			if(t[now].ch[z] == 0) return -1;
    			now = t[now].ch[z];
    		}
    		if(t[now].cnt == 0)	return -1;
    		if(t[now].bj == 1) return 1;
    		t[now].bj = 1;
    		return 0;
    	}	
    }TR;
    int z, ls, n;
    char S[510005];
    int main(){
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++){
    		scanf("%s", S + 1);
    		ls = strlen(S + 1);
    		TR.change(S, ls);	
    	}
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++){
    		scanf("%s", S + 1);
    		ls = strlen(S + 1);
    		int op = TR.query(S, ls);
    		if(op == 1)	puts("REPEAT");	
    		if(op == 0) puts("OK");
    		if(op == -1) puts("WRONG");	
    	}	
    }
    

    AC自动机:
    Trie图(AC自动机无fail指针,孩子如果为空直接指到相应的该去的差了好几次的有儿子的fail上)、fail树
    注意判是否出现过要沿着(fail)找一遍。

    struct AC_machine{
    	struct node{
    		int ch[26], nxt, cnt, bj;
    	}t[3000005];
    	int rt, tot;
    	int NEW(){
    		++tot;
    		memset(t[tot].ch, 0, sizeof(t[tot].ch));
    		t[tot].nxt = t[tot].cnt = t[tot].bj = 0; 
    		return tot;
    	}
    	void clear(){
    		tot = rt = 0;
    	}
    	void change(char *S, int ls){
    		int now = (rt = rt == 0 ? NEW() : rt);
    		for(int i = 1; i <= ls; i++){
    			int z = S[i] - 'a';
    			if(t[now].ch[z] == 0)
    				t[now].ch[z] = NEW();
    			now = t[now].ch[z];
    		}
    		t[now].bj = ++bh;
    	}
    	void init(){
    		Q.push(rt);
    		while(Q.size()){
    			int now = Q.front();
    			Q.pop();
    			for(int i = 0; i < 26; i++){
    				if(t[now].ch[i] == 0) continue;
    				int p = t[now].nxt;
    				while(p != 0 && t[p].ch[i] == 0) p = t[p].nxt;
    				if(p != 0) t[t[now].ch[i]].nxt= t[p].ch[i]; 
    				else t[t[now].ch[i]].nxt = rt;
    				Q.push(t[now].ch[i]);
    			}
    		}
    	}
    	int query(char *S, int ls){
    		int ans = 0;
    		int now = rt;
    		for(int i = 1; i <= ls; i++){
    			int z = S[i] - 'a';
    			while(now != rt && t[now].ch[z] == 0) now = t[now].nxt;
    			if(t[now].ch[z] == 0) continue;
    			now = t[now].ch[z];
    			int p = now;
    			while(p != rt){
    				if(t[p].bj)	t[p].cnt++;
    				if(ans < t[p].cnt){
    					ans = t[p].cnt;
    					V.clear();
    				}
    				if(ans == t[p].cnt) V.push_back(t[p].bj);				
    				p = t[p].nxt;
    			}
    		}
    		return ans;
    	}
    }ACM;
    

    后缀数组模板:

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    struct suffix_array{
    	int rk[2000005], sa[2000005], hr[2000005],/*(height)*/ hs[2000005];/*(h)*/
    	int bin[2000005], sz, tmp[2000005];
    	void build(char *S, int ls){
    		sz = max(ls, 255);
    		for(int i = 1; i <= ls; i++) rk[i] = S[i] + 1;
    		for(int i = 1; i <= sz; i++) bin[i] = 0;		
    		for(int i = 1; i <= ls; i++) bin[rk[i]]++; 
    		for(int i = 2; i <= sz; i++) bin[i] += bin[i - 1];
    		for(int i = ls; i >= 1; i--) sa[bin[rk[i]]--] = i;
    		for(int j = 1; j <= ls; j <<= 1){
    			int tot = 0;
    			for(int i = ls - j + 1; i <= ls; i++) tmp[++tot] = i;
    			for(int i = 1; i <= ls; i++) if(sa[i] - j > 0) tmp[++tot] = sa[i] - j;
    			for(int i = 1; i <= sz; i++) bin[i] = 0;
    			for(int i = 1; i <= sz; i++) bin[rk[i]]++;
    			for(int i = 2; i <= sz; i++) bin[i] += bin[i - 1];
    			for(int i = ls; i >= 1; i--) sa[bin[rk[tmp[i]]]--] = tmp[i];
    			tot = 1; tmp[sa[1]] = 1;
    			for(int i = 2; i <= ls; i++)
    				tmp[sa[i]] = rk[sa[i - 1] + j] == rk[sa[i] + j] && rk[sa[i - 1]] == rk[sa[i]] ? tot : ++tot;
    			for(int i = 1; i <= ls; i++) rk[i] = tmp[i];
    			if(tot == ls) break;
    		}
    		for(int i = 1; i <= ls; i++){
    			hs[i] = max(hs[i] - 1, 0);
    			while(S[i + hs[i]] == S[sa[rk[i] - 1] + hs[i]]) hs[i]++; 
    			hr[rk[i]] = hs[i];
    		}
    	}
    }SA;
    char S[2000005];
    int main() {
    	scanf("%s", S + 1);
    	int ls = strlen(S + 1);
    	SA.build(S, ls);
    	for(int i = 1; i <= ls; i++)
    		printf("%d ", SA.sa[i]);
    	return 0;
    }
    
  • 相关阅读:
    3.13作业 制作网页布局
    3.11 框架和样式表
    表单
    3.8学习记录
    第一次作业
    数据库增删改查
    数据库三大范式
    数据库中的时间戳
    数据库的主键与外键
    登录页面
  • 原文地址:https://www.cnblogs.com/Smeow/p/10578488.html
Copyright © 2011-2022 走看看