UVa 1673 str2int

来源:互联网 发布:淘宝导购怎么做 编辑:程序博客网 时间:2024/06/03 23:39

Rujia紫书上的例题(参见P392) , 以前一直以为CLJ是第一个将这玩意引进中国的 , 但其实早在2009年 , Rujia就将这一强有力的处理字符串的武器带给了我们。 本质上 , SAM就是DAWG的一个实例化 , 如果想对自动机有更深入的了解 , 推荐看看紫书。

此题几乎就是照着Rujia的讲解写的 , 因为代码仓库里没有这一章的代码 , 贴出来给大家参考。 唯一的不同是Rujia为了避免讨论广义后缀自动机 , 将字符串之间添加了junk字符来分割 , 但是这并不是必须的 , 只需要没次将last指针指向Root即可 , 这一方案第一次见到是去年浙江的省选题 , CLJ出的诸神眷顾的幻想乡。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <string>#include <vector>#include <deque>#include <stack>#include <queue>#include <set>#include <map>#include <algorithm>#include <cassert>using namespace std;const int modu = 2012;const int maxn = 2e5+1e2;const int maxnode = maxn;const int sigmaSize = 10;char s[maxn];int id(char c) { return c-'0'; }struct SAM{    int n , last;    int ch[maxnode][sigmaSize] , fa[maxnode] , mx[maxnode];    int c[maxn] , q[maxnode];    int sum[maxn] , cnt[maxn];    int newNode()       { mx[++n] = 0; memset(ch[n], 0, sizeof(ch[n])); return n; }    void init(){ mx[n = last = 1] = 0; memset(ch[1], 0, sizeof(ch[1]));           }    void extend(int x)    {        int p = last , np = newNode();         mx[last = np] = mx[p] + 1;        while(p && !ch[p][x]) ch[p][x] = np , p = fa[p];        if(!p) fa[np] = 1;        else         {            int q = ch[p][x];            if(mx[q] == mx[p]+1) fa[np] = q;            else             {                int nq = newNode();                mx[nq] = mx[p] + 1;                memcpy(ch[nq], ch[q], sizeof(ch[0]));                fa[nq] = fa[q];                fa[q] = fa[np] = nq;                while(p && ch[p][x] == q) ch[p][x] = nq , p = fa[p];            }        }    }    void sort()    {        memset(c, 0, sizeof(int)*(n+1));        for(int i=1;i<=n;i++) c[mx[i]]++;        for(int i=1;i<=n;i++) c[i] += c[i-1];        for(int i=1;i<=n;i++) q[c[mx[i]]--] = i;    }    int dp()    {        sort();        memset(sum, 0, sizeof(int)*(n+1));        memset(cnt, 0, sizeof(int)*(n+1));        sum[1] = 0; cnt[1] = 1;        for(int i=1 , j;i<=n;i++)        {            j = q[i];            for(int k=0,t;k<sigmaSize;k++)            {                if(j==1 && !k) continue;                t = ch[j][k];                (sum[t] += cnt[j]*k + sum[j]*10) %= modu;                (cnt[t] += cnt[j])               %= modu;            }        }        int res = 0;        for(int i=1;i<=n;i++) (res += sum[i]) %= modu;        return res;    }}solver;int n;int main(int argc, char *argv[]) {    while(cin>>n)    {        solver.init();        while(n--)        {            scanf("%s" , s);            solver.last = 1;            for(int i=0,j=strlen(s);i<j;i++) solver.extend(id(s[i]));        }        cout<<solver.dp()<<endl;    }    return 0;}
1 0
原创粉丝点击