zoukankan      html  css  js  c++  java
  • hdu 6208(后缀自动机、或者AC自动机

      题意:给你n个字符串,问你是否存在一个字符串可以从中找到其他n-1个字符串。

      思路:其实很简单,找到最长的那个字符串对他进行匹配,看是否能匹配到n-1个字符串。

      可以用AC自动机或者后缀自动机做,但是AC自动机用指针的话会MLE,但是我比赛的时候用自己的后缀自动机的板子T了!

      然后用了dalao的板子,还是我的板子不够优秀啊(┬_┬)

      AC自动机版:

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+100;
    const int maxm=50*10010;
    const int SIGMA_SIZE=26;
    int n;
    char t[maxn],s[maxn];
    
    struct AC
    {
        int ch[maxm][26];
        int val[maxm];
        int fail[maxm],last[maxm];
        int sz;
        void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;}
        int idx(char x){return x-'a';}
        void insert(char *s)
        {
            int u=0;
            int n=strlen(s);
            for(int i=0;i<n;i++)
            {
                int c=idx(s[i]);
                if(!ch[u][c])
                {
                    memset(ch[sz],0,sizeof(ch[sz]));
                    val[sz]=0;
                    ch[u][c]=sz++;
                }
                u=ch[u][c];
            }
            val[u]++;
        }
        void getfail()
        {
            queue<int> q;
            fail[0]=0;
            int u=0;
            for(int i=0;i<SIGMA_SIZE;i++)
            {
                u=ch[0][i];
                if(u){q.push(u);fail[u]=0;last[u]=0;}
            }
            while(!q.empty())
            {
                int r=q.front();q.pop();
                for(int i=0;i<SIGMA_SIZE;i++)
                {
                    u=ch[r][i];
                    if(!u){ch[r][i]=ch[fail[r]][i];continue;}
                    q.push(u);
                    int v=fail[r];
                    while(v&&!ch[v][i])v=fail[v];
                    fail[u]=ch[v][i];
                    last[u]=val[fail[u]]?fail[u]:last[fail[u]];
                }
            }
        }
        int find(char *s)
        {
            int u=0,cnt=0;
            int n=strlen(s);
            for(int i=0;i<n;i++)
            {
                int c=idx(s[i]);
                u=ch[u][c];
                int temp=0;//必须赋初值为0,表示如果下面两个判断都不成立的时候while可以正常执行
                if(val[u])
                    temp=u;
                else if(last[u])
                    temp=last[u];
                while(temp)
                {
                    cnt+=val[temp];
                    val[temp]=0;
                    temp=last[temp];
                }
            }
            return cnt;
        }
    }tree;
    string a[maxn];
    void solve()
    {
            scanf("%d",&n);
            tree.clear();
            int maxx=0, id=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%s",t);
                tree.insert(t);
                int len=strlen(t);
                if (len>maxx) {
                    maxx=len;
                    id=i;
                }
                a[i]=string(t);
            }
            tree.getfail();
            int len=a[id].length();
            for (int i=0; i<len; i++)
                t[i]=a[id][i];
            int ans=tree.find(t);
            //printf("%d
    ",ans);
            if (ans==n)  puts(t);
            else  puts("No");
    
    }
    int main() {
        int t = 1;
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        scanf("%d", &t);
        while(t--)
            solve();
        return 0;
    }

      后缀自动机:

    /** @xigua */
    #include <stdio.h>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <string>
    #include <map>
    #include <climits>
    #define PI acos(-1)
    #define rep(a,b,c) for(int (a)=(b); (a)<(c); ++(a))
    #define drep(a,b,c) for(int (a)=(b); (a)>(c); --(a))
    #define CLR(x) memset(x, 0, sizeof(x))
    #define sf scanf
    #define pf printf
    using namespace std;
    typedef long long ll;
    typedef double db;
    const int maxn = 1e5 + 1000;
    const int ma = 1e5 + 1000;
    const int mod = 1e9 + 7;
    const int INF = 1e8 + 5;
    const ll inf = 1e17 + 5;
    const db eps = 1e-6;
    const int MAXN = 2e5+1e3;
    char pool[MAXN];
    
    struct Str{
        int st, len;
    }str[MAXN];
    struct state {
        int len, pre, ch[26];
    };
    struct SAM {
        int sz, last;
        state st[MAXN];
        state& operator[] (int x) {
            return st[x];
        }
        void clear(int x) {
            CLR(st[x].ch);
        }
        void init() {
            sz=1, last=0;
            st[0].len=0, st[0].pre=-1;
            clear(0);
        }
        void add(int c) {
            int cur=sz++, p;
            clear(cur);
            st[cur].len=st[last].len+1;
            for(p=last; p!=-1&&!st[p].ch[c]; p=st[p].pre)
                st[p].ch[c]=cur;
            if(p==-1) st[cur].pre=0;
            else {
                int q=st[p].ch[c];
                if(st[q].len==st[p].len+1)
                    st[cur].pre=q;
                else {
                    int clone=sz++;
                    st[clone]=st[q];
                    st[clone].len=st[p].len+1;
                    st[cur].pre=st[q].pre=clone;
                    for(; p!=-1&&st[p].ch[c]==q; p=st[p].pre)
                        st[p].ch[c]=clone;
                }
            }
            last=cur;
        }
        int find(string t) {//查询lcs
            int now=0, l=0, ans=0;
            int len=t.length();
            for (int i=0; i<len; i++) {
                while(now&&!st[now].ch[t[i]-'a']) {
                    now=st[now].pre;
                    l=st[now].len;
                }
                if(st[now].ch[t[i]-'a']) {
                    ++l;
                    now=st[now].ch[t[i]-'a'];
                }
                ans=max(l, ans);
            }
            return ans;
        }
    } sam;
    string a[maxn];
    bool check(int sel, int n) {
        for (int i=0; i<n; i++) {
            if (i!=sel) {
                if (sam.find(a[i])!=a[i].length())  return 0;
            }
        }
        return true;
    }
    char ans[maxn];
    void solve() {
        int n;  scanf("%d", &n);
        str[0].st=0;
        int sel=0, maxx=0;
        for (int i=0; i<n; i++) {
            scanf("%s", pool);
            int len=strlen(pool);
            if (len>maxx)  {
                maxx=len;
                sel=i;
            }
            a[i]=string(pool);
        }
        sam.init();
        int len=a[sel].length();
        for (int i=0; i<len; i++)
            sam.add(a[sel][i]-'a');
        for (int i=0; i<len; i++)
            ans[i]=a[sel][i];
        if(check(sel,n)) {
            int l=a[sel].length();
            for (int i=0; i<len; i++)
                printf("%c", ans[i]);
                puts("");
        }
        else puts("No");
    }
    int main() {
        int t = 1, cas = 1;
        //freopen("in.txt", "r", stdin);
       // freopen("out.txt", "w", stdout);
        scanf("%d", &t);
        while(t--) {
           // printf("Case %d: ", cas++);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    template()方法
    如何引入模板引擎
    为什么使用模板引擎
    计算两个日期之间的天数
    oracle分析函数Rank, Dense_rank, row_number
    Oracle备份与恢复详解
    oracle的操作-表空间
    easyui API
    myeclipse快捷键代码
    Java 解决采集UTF-8网页空格变成问号乱码
  • 原文地址:https://www.cnblogs.com/gggyt/p/7544484.html
Copyright © 2011-2022 走看看