CSU1937: 小明的父亲

来源:互联网 发布:网络监控光纤收发器 编辑:程序博客网 时间:2024/04/30 09:13

#include"queue"#include"cstdio"#include"cstring"#include"iostream"#include"algorithm"using namespace std;typedef long long LL;const int N = 5e6+7;const int maxn = 1e6+7;const int MX = 30000 + 5;char s[maxn];char keyw[103],mp[1003][1003];int n,m,ans[3001];struct AC_machine {    int rear, root;    int Next[MX][26], Fail[MX], End[MX];    vector <int> id[MX];    void Init() {        rear = 0;        root = New();    }    int New() {        rear++;        End[rear] = 0;        id[rear].clear();        for(int i = 0; i < 26; i++) {            Next[rear][i] = -1;        }        return rear;    }    void Add(char*A,int I) {        int n = strlen(A), now = root;        for(int i = 0; i < n; i++) {            int id = A[i] - 'a';            if(Next[now][id] == -1) {                Next[now][id] = New();            }            now = Next[now][id];        }        End[now] = 1;        id[now].push_back(I);    }    void Build() {        queue<int>Q;        Fail[root] = root;        for(int i = 0; i < 26; 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 u = Q.front();            Q.pop();            for(int i = 0; i < 26; i++) {                if(Next[u][i] == -1) {                    Next[u][i] = Next[Fail[u]][i];                } else {                    Fail[Next[u][i]] = Next[Fail[u]][i];                    Q.push(Next[u][i]);                }            }        }    }    int Query(char *S) {        int n = strlen(S), now = 1, ret = 0;        for(int i = 0; i < n; i++) {            now = Next[now][S[i] - 'a'];            int temp = now;            while(temp != root) {                for(int j = 0; j < id[temp].size(); j++){                    int index = id[temp][j];                    ans[index] += End[temp];                }                temp = Fail[temp];            }        }        return ret;    }    void Print(int tot)    {        for(int i = 1; i <= tot; i++){            if(i > 1) printf(" ");            printf("%d",ans[i]);        }        puts("");    }}AC;int main(){    while(~scanf("%s",s)){        memset(ans,0,sizeof(ans));        scanf("%d%d",&n,&m);        for(int i = 1; i <= n; i++){            scanf("%s",mp[i]+1);        }        AC.Init();        int r,c,x,tot = 0;        scanf("%d%d",&r,&c);        for(int i = 1; i<= r; i++){            scanf("%d",&x);            AC.Add(mp[x]+1,++tot);        }        for(int i = 1; i<=c; i++){            scanf("%d",&x);            for(int j = 1; j <= n; j++){                keyw[j-1] = mp[j][x];            }            keyw[n] = 0;            AC.Add(keyw,++tot);        }        AC.Build();        AC.Query(s);        AC.Print(tot);    }    return 0;}

1937: 小明的父亲

        Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 64     Solved: 9    

Description

有一天小明的爸爸突然心血来潮想考验小明的记忆力,所以他出了这么个题目:
他给了小明一个字符串str,又给了他一个只包含小写字母n行m列的字符矩阵matrix
然后还有一串数字,r c a(0) a(1) a(2) ... a(r-1) b(0) b(1) b(2) ... b(c-1)
这表示从矩阵中提取字符串的提取规则。
提取规则为
a(0)行
a(1)行
a(2)行
...
a(r-1)行

b(0)列
b(1)列
b(2)列
...
b(c-1)列

小明的爸爸要小明从字符矩阵matrix中提取字符串,并告诉他这些字符串分别在字符串str中出现了多少次。

小明厌倦了他父亲的这种考验,所以他打算写个程序去自动计算,那么你可以帮助他吗?

Input

输入一个字符串str,长度小于1000000 输入一个n行m列的字符矩阵 1<=n,m<=100
输入一串数字用空格隔开
分别表示
r c a(0) a(1) a(2) ... a(r-1) b(0) b(1) b(2) ... b(c-1)
其中1<=r,c<=1000

Output

一串数字,表示结果,数字之间用空格隔开,行末无空格
分别表示你提取出来的字符串在str中出现的次数

Sample Input

aabaabaaaab4 5aabaaabbbaabaabaaaaa3 2 1 2 3 4 5

Sample Output

2 0 1 2 2

Hint

Source

2017年湖南多校对抗赛第10场

Author

xtu


AC自动机模板题,用id[]数组记录下答案的下标就行。