您的位置:首页 > 其它

ZOJ 3891 K-hash 后缀自动机

2015-08-26 11:13 253 查看
后缀自动机求不同的串,然后DP.....

K-hash
Time Limit: 2 Seconds      Memory Limit: 131072 KB

K-hash is a simple string hash function. It encodes a string Sconsist of digit characters into a K-dimensional vector (h0, h1, h2,...
, hK-1). If a nonnegative number xoccurs in S, then we call x is S-holded. And hi is the number of nonnegative numbers which are S-holded and congruent with i modulo K,
for i from 0 to K-1.
For example, S is "22014" and K=3. There are 12 nonnegative numbers are "22014"-holded: 0, 1, 2, 4, 14, 20, 22, 201, 220, 2014, 2201 and 22014. And three
of them, 0, 201 and 22014, are congruent with 0 modulo K, so h0=3. Similarly, h1=5 (1, 4, 22, 220 and 2014 are congruent with 1 modulo 3), h2=4(2, 14, 20 and 2201 are congruent with
2 modulo 3). So the 3-hash of "22014" is (3, 5, 4).
Please calculate the K-hash value of the given string S.

Input

There are multiple cases. Each case is a string S and a integer number K. (S is a string consist of '0', '1', '2', ... , '9' , 0< |S| ≤ 50000,
0< K≤ 32)

Output

For each case, print K numbers (h0, h1, h2,... , hK-1 ) in one line.

Sample Input

123456789 10
10203040506007 13
12345678987654321 2
112123123412345123456123456712345678123456789 17
3333333333333333333333333333 11

Sample Output

0 1 2 3 4 5 6 7 8 9
3 5 5 4 3 2 8 3 5 4 2 8 4
68 77
57 58 59 53 49 57 60 55 51 45 59 55 53 49 56 42 57
14 0 0 14 0 0 0 0 0 0 0

Author: ZHOU, Yuchen
Source: ZOJ Monthly, July 2023

/* ***********************************************
Author :CKboss
Created Time :2015年08月25日 星期二 10时22分16秒
File Name :ZOJ3891_2.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

const int maxn=100500;

struct SAM_Node
{
SAM_Node *fa,*next[10];
int len,id,pos;
SAM_Node(){}
SAM_Node(int _len)
{
fa=0; len=_len;
memset(next,0,sizeof(next));
}
};

SAM_Node SAM_node[maxn],*SAM_root,*SAM_last;
int SAM_size;

SAM_Node *newSAM_Node(int len)
{
SAM_node[SAM_size]=SAM_Node(len);
SAM_node[SAM_size].id=SAM_size;
return &SAM_node[SAM_size++];
}

SAM_Node *newSAM_Node(SAM_Node *p)
{
SAM_node[SAM_size]=*p;
SAM_node[SAM_size].id=SAM_size;
return &SAM_node[SAM_size++];
}

void SAM_init()
{
SAM_size=1;
SAM_root=SAM_last=newSAM_Node(0);
SAM_node[0].pos=0;
}

void SAM_add(int x,int len)
{
SAM_Node *p=SAM_last,*np=newSAM_Node(p->len+1);
np->pos=len; SAM_last=np;
for(;p&&!p->next[x];p=p->fa)
p->next[x]=np;
if(!p)
{
np->fa=SAM_root;
return ;
}
SAM_Node *q=p->next[x];
if(q->len==p->len+1)
{
np->fa=q;
return ;
}
SAM_Node *nq=newSAM_Node(q);
nq->len=p->len+1;
q->fa=nq; np->fa=nq;
for(;p&&p->next[x]==q;p=p->fa)
p->next[x]=nq;
}

void SAM_build(char *s)
{
SAM_init();
int len=strlen(s);
for(int i=0;i<len;i++)
SAM_add(s[i]-'0',i+1);
}

int du[maxn];
int ans[40];
int dp[maxn][40];

void solve(int K)
{
memset(du,0,sizeof(du));
for(int i=1;i<SAM_size;i++)
{
for(int j=0;j<10;j++)
{
SAM_Node* to=SAM_node[i].next[j];
if(to!=0) du[to->id]++;
}
}
queue<int> q;
for(int i=1;i<SAM_size;i++) if(du[i]==0) q.push(i);

memset(dp,0,sizeof(dp));

dp[1][0]=1;

while(!q.empty())
{
int u=q.front(); q.pop();

for(int i=0;i<10;i++)
{
SAM_Node* to=SAM_node[u].next[i];

if(to==0) continue;
else
{
int v=SAM_node[u].next[i]->id;
du[v]--;
if(du[v]==0) q.push(v);
if(u==1&&i==0) continue;
for(int j=0;j<K;j++)
{
dp[v][(j*10+i)%K]+=dp[u][j];
}
}
}
}
}

char str[maxn];
int k;

int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);

while(cin>>str>>k)
{
SAM_build(str);
solve(k);

memset(ans,0,sizeof(ans));

for(int i=2;i<SAM_size;i++)
for(int j=0;j<k;j++) ans[j]=ans[j]+dp[i][j];

for(int i=0,len=strlen(str);i<len;i++)
{
if(str[i]=='0') { ans[0]++; break; }
}

for(int i=0;i<k;i++)
printf("%d%c",ans[i],(i==k-1)?10:32);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: