ZOJ 3891 K-hash 后缀自动机

后缀自动机求不同的串,然后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 (h0h1h2,...
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 (h0h1h2,... , 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;
}

版权声明:来自: 码代码的猿猿的AC之路 http://blog.csdn.net/ck_boss

时间: 2024-11-05 21:47:57

ZOJ 3891 K-hash 后缀自动机的相关文章

BZOJ 3790 神奇项链 hash/后缀自动机+贪心

Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色. 为了制作这个项链,小 H 购买了两个机器.第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠.例如:aba和aca连接起来,可以生成串abaaca或 abaca. 现在给出目标项链的样式,询问你需要使用第二个机器多少次才

poj 2774 最长公共子串--字符串hash或者后缀数组或者后缀自动机

http://poj.org/problem?id=2774 想用后缀数组的看这里:http://blog.csdn.net/u011026968/article/details/22801015 本文主要讲下怎么hash去找 开始的时候写的是O(n^2 logn)算法 果断超时...虽然也用了二分的,, 代码如下: //hash+二分 #include <cstdio> #include <cstring> #include <algorithm> #include

2019年华南理工大学程序设计竞赛(春季赛) K Parco_Love_String(后缀自动机)找两个串的相同字串有多少

https://ac.nowcoder.com/acm/contest/625/K 题意: 给出Q 个询问 i , 求 s[0..i-1] 与 s[i...len-1] 有多少相同的字串 分析: 给出了查询 , 容易想到先预处理出答案好吧 , 字符串的问题也容易想到后缀自动机 ,但是我们该怎么使用呢? 下面提供我的思路: 我们建立出SAM后 , 跑一边拓扑排序 ,根据SAM跑出来的拓扑排序的序列特性 , 我们可以求出 在当前状态st 的最大串字符出现的个数 for (int i = now; i

[转]后缀自动机

原文地址:http://blog.sina.com.cn/s/blog_8fcd775901019mi4.html 感觉自己看这个终于觉得能看懂了!也能感受到后缀自动机究竟是一种怎样进行的数据结构了... 笔者自己的话会用楷体表示出来...[说不定能帮助大家理解,但是可能也破坏了大家的自主理解力?所以...看不懂的话再来看好咯...] 常用的字符串处理工具: 1.       整词索引:排序+二分:Hash表.可以解决整词匹配,但不支持前缀搜索:Hash表在模式串定长的情况下可以用RK解决多模式

ZOJ 3891 K-hash

K-hash Time Limit: 2000ms Memory Limit: 131072KB This problem will be judged on ZJU. Original ID: 389164-bit integer IO format: %lld      Java class name: Main K-hash is a simple string hash function. It encodes a string Sconsist of digit characters

hdu 4622 Reincarnation(后缀数组|后缀自动机|KMP)

Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 2138    Accepted Submission(s): 732 Problem Description Now you are back,and have a task to do: Given you a string s consist of lo

【后缀自动机】spoj1811-LCS

题意 给你两个字符串,求他们的LCS的长度 N <= 2.5e5 时限0.25s左右 后缀自动机练习...不知道hash行不行我想去试一发. 本题要用到的是后缀自动机的一个性质: 构建自动机时用到的step数组,之前以为是没什么用的,原来还能这样,长知识了. step[i]表示的是[从root节点走到i这个节点,经过了几个字符],这个性质在匹配时失配的情况下可以用来更新当前答案. 利用第一个字符串建立一个SAM,然后用第二个字符串来在自动机上进行匹配,看看最长能匹配多远就是答案了. 在失配的时候

【后缀自动机】SPOJ 1812-LCSII

题意: 给出最多10个长度不超过100000的字符串,求他们的LCS的长度.时限是鬼畜的0.25s . 后缀自动机练习...虽然有人这么说但我并不觉得hash能过. 本题可以说是[论SAM中按step排序更新pre的重要性]: 总的来说做法和1811-LCS有点类似,不同的是因为有多个字符串,因此每个字符串都需要在SAM上跑一次. 记录下每个节点最长能容纳长度为多少的字符,最后取个MAX就行了. 用nans[i]表示匹配当前字符串时,i号点能容纳的子串长度,如果i的pre上的当前答案比i还要小的

HDU 4622 Reincarnation 后缀自动机

Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Problem Description Now you are back,and have a task to do:Given you a string s consist of lower-case English letters only,denote f(s) as the number of