【CUC集训】字典树+kmp+字符串hash题解


  • 制作:数字_ID
  • 日期:2018年8月27日

A (HDU - 2087)

  • 简单KMP,注意匹配成功之后j归0
#include   
#include    
#include   
using namespace std;  
int nexta[1006];  
char t[1006],s[1006];  
void getnexta(char s[])  
{  
    memset(nexta,0,sizeof(nexta));  
    int n = strlen(s);  
    int k = -1,j = 0;  
    nexta[0] = -1;  
    while(j < n )  
    {  
  
        if(k == -1 || s[k] == s[j])  
        {  
            nexta[j + 1] = k + 1;  
            j ++;  
            k ++;  
        }  
        else  
        {  
            k = nexta[k];  
        }  
    }  
  
}  
int kmp(char s[],char t[])//t模式串,s母串.此种为返回首次匹配的位置,不能匹配则返回-1.  
{  
    getnexta(t);  
    int ans = 0;  
    int n = strlen(s),m = strlen(t);  
    int i = 0,j = 0;  
    while(i < n && j < m)  
    {  
        if(j == -1 || s[i] == t[j])  
        {  
            i ++;  
            j ++;  
        }  
        else  
        {  
            j = nexta[j];  
        }  
        if(j == m)//根据题目要求改变  
        {  
            ans ++;  
            j = 0;  
        }  
    }  
    return ans;  
}  
int main()  
{  
   // freopen("in.txt","r",stdin);  
    while(1)  
    {  
        scanf("%s",s);  
        if(strcmp(s,"#") == 0)  
            break;  
        scanf("%s",t);  
        printf("%d\n",kmp(s,t));  
    }  
    return 0;  
}  

B(HDU - 1711)

  • kmp入门模板题
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# define INF 0x3f3f3f3f
# define clr0(x) memset(x,0,sizeof(x))
# define clr1(x) memset(x,INF,sizeof(x))
# define clrf(x) memset(x,-1,sizeof(x))
# define rep(i,a) for(int i = 0;i<(a);i++)
# define repf(i,a,b) for(int i = (a);i<=(b);i++)
# define repu(i,a,b) for(int i = (a);i<(b);i++)
# define repd(i,a,b) for(int i = (a);i>=(b);i--)
# define lowbit x&(-x)
# define W(a) while(a)
# define Sc(x) scanf("%d",&(x))
# define Sd(x) scanf("%I64d",&(x))
# define Lson(x) (x)<<1
# define Rson(x) (x)<<1|1
# define ll long long
# define fuckio ios::sync_with_stdio(false);
# define fuck cout<<"fucl:"<<__LINE__<

C(HDU - 1686)

  • kmp统计子串格式
  • 可重叠
  • 注意匹配成功之后j=nexta[j]
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# define INF 0x3f3f3f3f
# define clr0(x) memset(x,0,sizeof(x))
# define clr1(x) memset(x,INF,sizeof(x))
# define clrf(x) memset(x,-1,sizeof(x))
# define rep(i,a) for(int i = 0;i<(a);i++)
# define repf(i,a,b) for(int i = (a);i<=(b);i++)
# define repu(i,a,b) for(int i = (a);i<(b);i++)
# define repd(i,a,b) for(int i = (a);i>=(b);i--)
# define lowbit x&(-x)
# define W(a) while(a)
# define Sc(x) scanf("%d",&(x))
# define Sd(x) scanf("%I64d",&(x))
# define Lson(x) (x)<<1
# define Rson(x) (x)<<1|1
# define ll long long
# define fuckio ios::sync_with_stdio(false);
# define fuck cout<<"fucl:"<<__LINE__<>T;
    W(T--){
       cin>>t>>s;
       cout<

D(HDU - 3746)

  • next数组的一共经典应用,统计字符串的循环节
  • 希望大家这道题都能搞明白
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# define INF 0x3f3f3f3f
# define clr0(x) memset(x,0,sizeof(x))
# define clr1(x) memset(x,INF,sizeof(x))
# define clrf(x) memset(x,-1,sizeof(x))
# define rep(i,a) for(int i = 0;i<(a);i++)
# define repf(i,a,b) for(int i = (a);i<=(b);i++)
# define repu(i,a,b) for(int i = (a);i<(b);i++)
# define repd(i,a,b) for(int i = (a);i>=(b);i--)
# define lowbit x&(-x)
# define W(a) while(a)
# define Sc(x) scanf("%d",&(x))
# define Sd(x) scanf("%I64d",&(x))
# define Lson(x) (x)<<1
# define Rson(x) (x)<<1|1
# define ll long long
# define fuckio ios::sync_with_stdio(false);
# define fuck cout<<"fucl:"<<__LINE__<>s;
        getnxt(s);
        int len = s.length();
        int min_repeat=len-nexta[len];
        if(len!=min_repeat&&len%min_repeat==0)  
            printf("0\n");
        else
            printf("%d\n",min_repeat-len%min_repeat); 

    }
}

E(HDU - 1251)

  • 字典树板子题,flag维护前缀出现的次数
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# define INF 0x3f3f3f3f
# define clr0(x) memset(x,0,sizeof(x))
# define clr1(x) memset(x,INF,sizeof(x))
# define clrf(x) memset(x,-1,sizeof(x))
# define rep(i,a) for(int i = 0;i<(a);i++)
# define repf(i,a,b) for(int i = (a);i<=(b);i++)
# define repu(i,a,b) for(int i = (a);i<(b);i++)
# define repd(i,a,b) for(int i = (a);i>=(b);i--)
# define lowbit x&(-x)
# define W(a) while(a)
# define Sc(x) scanf("%d",&(x))
# define Sd(x) scanf("%I64d",&(x))
# define Lson(x) (x)<<1
# define Rson(x) (x)<<1|1
# define ll long long
# define fuckio ios::sync_with_stdio(false);
# define fuck cout<<"fuck:"<<__LINE__<flag++;
        int to = s[i]-'a';
        if(now->nxt[to] == NULL)now->nxt[to] = new Node();
        now = now->nxt[to];
    }
    now->flag++;
}

int fid(char *s)
{
    int len = strlen(s);
    Node *now = root;
    rep(i,len){
        int to = s[i]-'a';
        if(now->nxt[to] == NULL)return 0;
        now = now->nxt[to];
    }
    return now->flag;
}


int main()
{
    fuckio
    char s[11];
    init();
    W(cin.getline(s,12)){
        if(strlen(s) == 0||s[0] == ' ')break;
        ins(s);
    }
    W(scanf("%s",s)!=EOF){
        printf("%d\n",fid(s));
    }
}

F(HihoCoder - 1366)

  • 本来想让大家试着用字典树做,但时限给了10s,自然也就能用stl直接做
  • 正序查找,倒叙插入
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# define INF 0x3f3f3f3f
# define clr0(x) memset(x,0,sizeof(x))
# define clr1(x) memset(x,INF,sizeof(x))
# define clrf(x) memset(x,-1,sizeof(x))
# define rep(i,a) for(int i = 0;i<(a);i++)
# define repf(i,a,b) for(int i = (a);i<=(b);i++)
# define repu(i,a,b) for(int i = (a);i<(b);i++)
# define repd(i,a,b) for(int i = (a);i>=(b);i--)
# define lowbit x&(-x)
# define W(a) while(a)
# define Sc(x) scanf("%d",&(x))
# define Sd(x) scanf("%I64d",&(x))
# define Lson(x) (x)<<1
# define Rson(x) (x)<<1|1
# define ll long long
# define fuckio ios::sync_with_stdio(false);
# define fuck cout<<"fuck:"<<__LINE__<nxt[to] == NULL)now->nxt[to] = new Node();
        now = now->nxt[to];
    }
    now->flag++;
}

int fid(char *s)
{
    int len = strlen(s);
    Node *now = root;
    rep(i,len){
        int to = s[i]-'a';
        if(now->nxt[to] == NULL)return 0;
        now = now->nxt[to];
    }
    return now->flag;
}


int main()
{
    fuckio
    int n;Sc(n);
    int ans = 0;
    char s[30];
    init();
    W(n--){
        scanf("%s",s);
        ans += fid(s);
        ins(s);
        clr0(s);
    }
    printf("%d\n",ans);
}

G(UVA - 12338)

  • 提议是询问两个字串的最长前缀匹配
  • 符串hash+二分,hash的一个经典应用
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# define INF 0x3f3f3f3f
# define clr0(x) memset(x,0,sizeof(x))
# define clr1(x) memset(x,INF,sizeof(x))
# define clrf(x) memset(x,-1,sizeof(x))
# define rep(i,a) for(int i = 0;i<(a);i++)
# define repf(i,a,b) for(int i = (a);i<=(b);i++)
# define repu(i,a,b) for(int i = (a);i<(b);i++)
# define repd(i,a,b) for(int i = (a);i>=(b);i--)
# define lowbit x&(-x)
# define W(a) while(a)
# define Sc(x) scanf("%d",&(x))
# define Sd(x) scanf("%I64d",&(x))
# define Lson(x) (x)<<1
# define Rson(x) (x)<<1|1
# define ll long long
# define fuckio ios::sync_with_stdio(false);
# define fuck cout<<"fuck:"<<__LINE__<hashcode[maxn];
char str[maxn];
int strhash[maxn];

void gethash(int pos)
{
    int len = strlen(str);
    strhash[pos] = len;
    hashcode[pos].clear();
    hashcode[pos].push_back(0);
    repf(i,1,len)hashcode[pos].push_back(hashcode[pos][i-1]*233+str[i-1]);
}


int main()
{
    fuckio
    int T,N,Q,a,b,l,r,mid;
    Sc(T);
    repf(tt,1,T){
        printf("Case %d:\n",tt);
        Sc(N);
        repf(i,1,N){
            scanf("%s",str);
            gethash(i);
        }
        Sc(Q);
        W(Q--){
            scanf("%d%d",&a,&b);
            int len = min(strhash[a],strhash[b]);
            l = 0;r = len;
            W(l

H(HDU - 4300)

  • 给一个代换表,给一个混合明密文,密文完整明文缺失,问要补充的最小字符数
  • 两个hash,假设全部是密文,翻译过来之后计算hash,已经翻译之前计算hash。从len/2枚举密文长度,翻译后的密文前缀和翻译前的明文后缀
  • 扩展kmp也可做
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# define INF 0x3f3f3f3f
# define clr0(x) memset(x,0,sizeof(x))
# define clr1(x) memset(x,INF,sizeof(x))
# define rep(i,a) for(int i = 0;i<(a);i++)
# define repf(i,a,b) for(int i = (a);i<=(b);i++)
# define repu(i,a,b) for(int i = (a);i<(b);i++)
# define repd(i,a,b) for(int i = (a);i>=(b);i--)
# define lowbit x&(-x)
# define W(a) while(a)
# define Sc(x) scanf("%d",&(x))
# define Lson(x) (x)<<1
# define Rson(x) (x)<<1|1
# define ll long long
# define fuckio ios::sync_with_stdio(false);
# define fuck cout<<"fuck:"<<__LINE__<

J(HDU - 4825)

  • 从已知集合中选一个数是的询问中的数与选的这个数的异或值最大
  • 01字典树,从高位到低位建树,贪心
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# define INF 0x3f3f3f3f
# define clr0(x) memset(x,0,sizeof(x))
# define clr1(x) memset(x,INF,sizeof(x))
# define rep(i,a) for(int i = 0;i<(a);i++)
# define repf(i,a,b) for(int i = (a);i<=(b);i++)
# define repu(i,a,b) for(int i = (a);i<(b);i++)
# define repd(i,a,b) for(int i = (a);i>=(b);i--)
# define lowbit x&(-x)
# define W(a) while(a)
# define Sc(x) scanf("%d",&(x))
# define Lson(x) (x)<<1
# define Rson(x) (x)<<1|1
# define ll long long
# define fuckio ios::sync_with_stdio(false);
# define fuck cout<<"fuck:"<<__LINE__<>i)&1;
        //cout<nxt[to] == NULL)now->nxt[to] = new Node();
        now = now->nxt[to];
    }
    now->flag = s;
}

int fid(int s)
{
    Node *now = root;
    int len = 32;
    
    repd(i,len-1,0){
        int to =  (s>>i)&1;
        
        if(now->nxt[to^1] != NULL){
            //cout<<(to+1)%2<<" ";
            now = now->nxt[to^1];
        }else {
            //cout<nxt[to];
        }
    }
    return now->flag;
}


int main()
{
    fuckio
    int T;Sc(T);
    int n,m;
    repf(tt,1,T){
        printf("Case #%d:\n",tt);
        init();
        Sc(n);Sc(m);
        rep(i,n){
            int a;Sc(a);
            //cout<

你可能感兴趣的:(【CUC集训】字典树+kmp+字符串hash题解)