zoukankan      html  css  js  c++  java
  • [SPOJ705]不同的子串

    题目点这里

    我们发现这道题可以用后缀自动机做(不会的点这里

    我们发现后缀自动机每条路径代表一条子串,那么我们就DP:

    写法一

    #include<bits/stdc++.h>
    #define N 100071
    using namespace std;
    struct Node{
        int c[26],fa,val;
    }T[N];
    int tot=1,last=1,D[N],c[N],np,q,nq,len,id[N],ans;
    char ch[N];
    inline void Sam(int x){
        np=++tot; T[np].val=T[last].val+1;
        for (;last&&!T[last].c[x];last=T[last].fa) T[last].c[x]=np;
        if (!last) T[np].fa=1;
        else { q=T[last].c[x];
         if (T[q].val==T[last].val+1) T[np].fa=q;
         else  {
             nq=++tot; T[nq]=T[q];
             T[nq].val=T[last].val+1; T[np].fa=T[q].fa=nq;
             for (;last&&T[last].c[x]==q;last=T[last].fa) T[last].c[x]=nq;
         }
        } last=np; 
    }
    int main () {
        freopen("subst1.in","r",stdin);
        freopen("subst1.out","w",stdout);
        scanf("%s",ch+1);len=strlen(ch+1);
        for (int i=1;i<=len;i++)
         Sam(ch[i]-'A');
        for (int i=1;i<=tot;i++) c[T[i].val]++,D[i]=1;
        for (int i=1;i<=len;i++) c[i]+=c[i-1];
        for (int i=1;i<=tot;i++) id[c[T[i].val]--]=i;
        for (int i=tot;i;i--) 
         for (int j=0;j<26;j++)
          D[id[i]]+=D[T[id[i]].c[j]];
        printf("%d
    ",D[1]-1); 
    //    for (int i=tot;i;i--) ans+=T[i].val-T[T[i].fa].val;
    //    printf("%d
    ",ans);
        return 0;
    }

    我们可以把DP方程化简一下,得到写法二

    #include<bits/stdc++.h>
    #define N 100071
    using namespace std;
    struct Node{
        int c[26],fa,val;
    }T[N];
    int tot=1,last=1,D[N],c[N],np,q,nq,len,id[N],ans;
    char ch[N];
    inline void Sam(int x){
        np=++tot; T[np].val=T[last].val+1;
        for (;last&&!T[last].c[x];last=T[last].fa) T[last].c[x]=np;
        if (!last) T[np].fa=1;
        else { q=T[last].c[x];
         if (T[q].val==T[last].val+1) T[np].fa=q;
         else  {
             nq=++tot; T[nq]=T[q];
             T[nq].val=T[last].val+1; T[np].fa=T[q].fa=nq;
             for (;last&&T[last].c[x]==q;last=T[last].fa) T[last].c[x]=nq;
         }
        } last=np; 
    }
    int main () {
        freopen("subst1.in","r",stdin);
        freopen("subst1.out","w",stdout);
        scanf("%s",ch+1);len=strlen(ch+1);
        for (int i=1;i<=len;i++)
         Sam(ch[i]-'A');
    //    for (int i=1;i<=tot;i++) c[T[i].val]++,D[i]=1;
    //    for (int i=1;i<=len;i++) c[i]+=c[i-1];
    //    for (int i=1;i<=tot;i++) id[c[T[i].val]--]=i;
    //    for (int i=tot;i;i--) 
    //     for (int j=0;j<26;j++)
    //      D[id[i]]+=D[T[id[i]].c[j]];
    //    printf("%d
    ",D[1]-1); 
        for (int i=tot;i;i--) ans+=T[i].val-T[T[i].fa].val;
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    获取Enum枚举值描述的几法方法
    Android开发入门 Button事件实现的方法(原创)
    最有价值的.Net第三方控件
    Eclipse快捷键大全(转载)
    recovery教程
    XP系统通过无线网卡共享宽带给其他设备,正确的共享设置(修正版,绝对可行)
    使用Eclipse写QT
    Android 4.0模拟器弹出“谷歌拼音输入法”已停止运行的解决方法
    C# 枚举用法总结
    谷歌安卓系统使用必读,什么是root, Recovery, Radio, APP TO SD, Rom
  • 原文地址:https://www.cnblogs.com/rrsb/p/8277736.html
Copyright © 2011-2022 走看看