2017年07月30日

来源:互联网 发布:linux find mtime时间 编辑:程序博客网 时间:2024/05/24 04:11

醉了,看个ac自动机的模板,,照着别人的敲都敲不对。
还是看kuangbin大神的吧。。。

http://www.cnblogs.com/kuangbin/p/3164106.html
参看J

这种找源代码。。我还是用博客的巴,尽量不要照着敲。要不然没得复制就不知道怎么班。。
病毒侵袭模板。。。

struct Trie{    int next[N][128],fail[N],end[N];    int root,L;    int newnode() {        for(int i = 0;i < 128;i++)            next[L][i] = -1;        end[L++] = -1;        return L-1;    }    void init() {        L = 0;        root = newnode();    }    void insert(char s[],int id) {        int len = strlen(s);        int now = root;        for(int i = 0;i < len;i++) {            if(next[now][s[i]] == -1)                next[now][s[i]] = newnode();            now=next[now][s[i]];        }        end[now]=id;    }    void build() {        queue<int>Q;        fail[root] = root;        for(int i = 0;i < 128;i++)            if(next[root][i] == -1)                next[root][i] = root;            else {                fail[next[root][i]] = root;                Q.push(next[root][i]);            }        while(!Q.empty()) {            int now = Q.front();            Q.pop();            for(int i = 0;i < 128;i++)                if(next[now][i] == -1)                    next[now][i] = next[fail[now]][i];                else {                    fail[next[now][i]] = next[fail[now]][i];                    Q.push(next[now][i]);                }        }    }    bool used[510];    bool query(char buf[],int n,int id) {        int len = strlen(buf);        int now = root;        memset(used,false,sizeof(used));        bool flag = false;        for(int i = 0;i < len;i++)        {            now = next[now][buf[i]];            for(int temp=now;temp!=root;temp=fail[temp]){                if(end[temp]!=-1){                    used[end[temp]]=true;                    flag=true;                }            }        }        if(!flag)return false;        printf("web %d:",id);        for(int i = 1;i <= n;i++)            if(used[i])                printf(" %d",i);        printf("\n");        return true;    }}ac;

然后终于把那个最入门的模板提做了。。。
感觉好多坑。。
https://vjudge.net/contest/172503#problem/C
和上题差不多。。
但是我的想法比较复杂。。然后又看题解了。。发现题解直接用终止节点就记录id。然后枚举就顺序输出叻。
然后自己忘了build。。。。查了挺久的。。
然后别人的没有去掉不是大写字母的。。分支128 。。

https://vjudge.net/contest/172503#problem/H
看kuangbin大神的。。原来可以这样加个数组判断不可以重复的情况
他这里对于每一个单词的深度deep都有记录。。。感觉是挺难想的。。

https://vjudge.net/contest/172503#problem/G
第一道ac自动机+dp的题目,对于他这种按照自动机上有没有指针的方式来判断可不可dp的方式自己确实没有见过。。

感觉这个dp做了之后对ac自动机的模式比较了解了。。注意什么地方要改。。
参考http://blog.csdn.net/human_ck/article/details/6577142

#include<algorithm>#include<vector>#include<cstring>#include<string>#include<iomanip>#include<cstdio>#include<stack>#include<iostream>#include<map>#include<queue>using namespace std;#define sf scanf#define pf printf#define mem(a,b) memset(a,b,sizeof(a));#define rep(i,a,b) for(int i=(a);i<=(b);++i)#define bug1 puts("bug1");#define bug2 puts("bug2");#define bug3 puts("bug3");#define N 26*55#define M 200#define ULL unsigned long long#define LL long longconst int INF=1e9;const int inf=0x3f3f3f3f;//2017年07月30日20:44:28int len;int dp[1010][20*26];char s[1010];inline int getcode(char c){    if(c=='A')return 0;    if(c=='G')return 1;    if(c=='C')return 2;    if(c=='T')return 3;}struct Trie{    int next[N][4],fail[N],end[N];    int root,L;    int newnode() {        for(int i = 0;i < 4;i++)            next[L][i] = -1;        end[L++] = 0;        return L-1;    }    void init() {        L = 0;        root = newnode();    }    void insert(char s[]) {        int len = strlen(s);        int now = root;        for(int i = 0;i < len;i++) {            int index=getcode(s[i]);            if(next[now][index] == -1)                next[now][index] = newnode();            now=next[now][index];        }        end[now]=1;    }    void build() {        queue<int>Q;        fail[root] = root;        for(int i = 0;i < 4;i++)            if(next[root][i] == -1)                next[root][i] = root;            else {                fail[next[root][i]] = root;                Q.push(next[root][i]);            }        while(!Q.empty()) {            int now = Q.front();            Q.pop();            for(int i = 0;i < 4;i++)                if(next[now][i] == -1)                    next[now][i] = next[fail[now]][i];                else {                    fail[next[now][i]] = next[fail[now]][i];//这个地方注意为什么要这样改。                    if(end[fail[next[now][i]]])end[next[now][i]]=1;                    Q.push(next[now][i]);                }        }    }    int solve(){        int tot=L-1;        for(int i=0;i<=len;++i){            for(int j=0;j<=tot;++j){                dp[i][j]=inf;            }        }        dp[0][0]=0;        for(int i=1;i<=len;++i){            for(int j=0;j<=tot;++j){                if(dp[i-1][j]<inf){                    for(int k=0;k<4;++k){                        if(end[next[j][k]]==0){                            dp[i][next[j][k]]=min(dp[i][next[j][k]],dp[i-1][j]+(getcode(s[i])!=k));                        }                    }                }            }        }        int ans=inf;        for(int i=0;i<=tot;++i){            if(dp[len][i]<ans&&end[i]==0)                ans=dp[len][i];        }        if(ans==inf)return -1;        return ans;    }}ac;int main(){    int n;int cas=0;    while(~sf("%d",&n)&&n!=0){        mem(dp,inf);        ac.init();        rep(i,1,n){            char t[22];sf("%s",t);ac.insert(t);        }        ac.build();        sf("%s",s+1);        len=strlen(s+1);        int ret=ac.solve();        if(ret==-1)pf("Case %d: -1\n",++cas);        else pf("Case %d: %d\n",++cas,ret);    }}

https://vjudge.net/contest/172503#problem/S
字符串hash。。 不过这是很初级的了。。。/
https://vjudge.net/contest/172503#problem/D
这题还没看懂。。因为对于矩阵快速幂不熟,而且不知道为什么要这样。。。

原创粉丝点击