考的时候脑子各种短路,用个SAM瞎搞了半天没搞出来,最后中午火急火燎的打了个SPFA才混了点分。

其实这个可以把每个模式串长度为$K-1$的字符串看作一个状态,这个用字符串Hash实现,然后我们发现这实际上可以通过不断转移变成一个DAG,通过topsort即可算出最优解。

我怎么就那么脑残没想到呢..

//rhyme
//by Cydiater
//2017.2.19
#include <iostream>
#include <cstdio>
#include <queue>
#include <map>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <cmath>
#include <bitset>
#include <set>
#include <vector>
#include <complex>
using namespace std;
#define ll long long
#define up(i,j,n)	for(int i=j;i<=n;i++)
#define down(i,j,n)	for(int i=j;i>=n;i--)
#define cmax(a,b)	a=max(a,b)
#define cmin(a,b)	a=min(a,b)
#define FILE		"rhyme"
#define Auto(i,node)	for(int i=LINK[node];i;i=e[i].next)
#define pii		pair<int,int>
#define Map		map<pii,int>
const int MAXN=3e5+5;
const int oo=0x3f3f3f3f;
const int base1=130069;
const int base2=136027;
const int mod1=9179767;
const int mod2=9832517;
inline int read(){
	char ch=getchar();int x=0,f=1;
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int N,K,cnt=1;
char s[MAXN];
struct Hash{
	int bin[MAXN],hash[MAXN],base,mod;
	void Ready(int Base,int Mod){
		base=Base;mod=Mod;
		int len=strlen(s+1);
		bin[0]=1;hash[0]=0;
		up(i,1,len){
			bin[i]=(1LL*bin[i-1]*base)%mod;
			hash[i]=(1LL*hash[i-1]*base%mod+s[i]-17+mod)%mod;
		}
	}
	int get(int L,int R){
		return ((hash[R]-1LL*hash[L-1]*bin[R-L+1]%mod+mod)%mod+mod)%mod;
	}
}h1,h2;
namespace Graph{
	struct edge{
		int y,next;
	}e[MAXN<<1];
	int LINK[MAXN],len=0,deg[MAXN],q[MAXN],head,tail,dis[MAXN];
	bool vis[MAXN];
	pii E[MAXN<<1];
	void reset(){
		len=0;
		memset(LINK,0,sizeof(LINK));
		memset(vis,0,sizeof(vis));
		memset(deg,0,sizeof(deg));
	}
	inline void insert(int x,int y){
		e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;
		deg[y]++;E[len]=make_pair(x,y);
	}
	void Topsort(int cnt){
		head=1;tail=0;
		int tol=len;reset();len=tol;
		up(i,1,tol)insert(E[i].second,E[i].first);
		memset(dis,0,sizeof(dis));
		up(i,1,cnt)if(!deg[i]){
			q[++tail]=i;
			dis[i]=1;
		}
		for(;head<=tail;head++){
			int node=q[head];
			Auto(i,node)if(!--deg[e[i].y]){
				cmax(dis[e[i].y],dis[node]+1);
				q[++tail]=e[i].y;
			}
		}
		up(i,1,cnt)if(deg[i])dis[1]=oo;
	}
}
Map ID;
namespace solution{
	void Prepare(){
		Graph::reset();
		ID.erase(ID.begin(),ID.end());
		cnt=1;
		up(i,1,N){
			using namespace Graph;
			scanf("%s",s+1);int len=strlen(s+1);
			if(len<K)continue;
			h1.Ready(base1,mod1);h2.Ready(base2,mod2);
			pii last=make_pair(h1.get(1,K-1),h2.get(1,K-1)),now;
			if(!ID[last]){
				ID[last]=++cnt;
				insert(1,cnt);
			}
			up(j,K,len){
				now=make_pair(h1.get(j-K+2,j),h2.get(j-K+2,j));
				if(!ID[now]){
					ID[now]=++cnt;
					insert(1,cnt);
				}
				insert(ID[last],ID[now]);
				last=now;
			}
		}
	}
	void Solve(){
		Graph::Topsort(cnt);
		if(Graph::dis[1]==oo){
			puts("INF");
			return;
		}
		printf("%d\n",Graph::dis[1]+K-3==K-2?K-1:Graph::dis[1]+K-3);
	}
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	using namespace solution;
	while(scanf("%d%d",&N,&K)!=EOF){
		Prepare();
		Solve();
	}
	return 0;
}

[省选模拟]Rhyme的更多相关文章

  1. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  2. 省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)

    一 稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数 一个挺trick的想法是: 由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和 那么如果把不存在于原树中的 ...

  3. NOI2019省选模拟赛 第五场

    爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...

  4. NOI2019省选模拟赛 第六场

    传送门 又炸了-- \(A\) 唐时月夜 不知道改了什么东西之后就\(A\)掉了\(.jpg\) 首先,题目保证"如果一片子水域曾经被操作过,那么在之后的施法中,这片子水域也一定会被操作&q ...

  5. 省选模拟赛 arg

    1 arg (arg.cpp/in/out, 1s, 512MB)1.1 Description给出一个长度为 m 的序列 A, 请你求出有多少种 1...n 的排列, 满足 A 是它的一个 LIS. ...

  6. 【NOI省选模拟】小奇的花园

    「题目背景」 小奇在家中的花园漫步时,总是会思考一些奇怪的问题. 「问题描述」 小奇的花园有n个温室,标号为1到n,温室以及以及温室间的双向道路形成一棵树. 每个温室都种植着一种花,随着季节的变换,温 ...

  7. [JZOJ6257] 【省选模拟8.9】修路

    题目 题目大意 有一堆点,每个点都有其权值\(c_i\). 每次插入边\((u,v)\),\(u\)和\(1\)连通,\(v\)和\(1\)不连通.最后保证形成一棵树. 每次插入的时候询问\(1\)到 ...

  8. @省选模拟赛03/16 - T3@ 超级树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...

  9. 5.10 省选模拟赛 拍卖 博弈 dp

    LINK:拍卖 比赛的时候 前面时间浪费的有点多 写这道题的时候 没剩多少时间了. 随便设了一个状态 就开始做了. 果然需要认真的思考.其实 从我的状态的状态转移中可以看出所有的结论. 这里 就不再赘 ...

随机推荐

  1. ZOJ 3780 - Paint the Grid Again - [模拟][第11届浙江省赛E题]

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3780 Time Limit: 2 Seconds      Me ...

  2. cordova 加载HTML 资源的次序

    ionic 开发的app再启动的时候不会很快,因为cordova 会加载html,css, js这些文件,读取这些文件内的代码之后,js代码才能和Native建立桥接. 这是一个初始化运行时环境的操作 ...

  3. iOS多线程编程之创建线程安全(转载)

    一.多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象.同一个变量.同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数 ...

  4. 读取Excel列,转换为String输出(Java实现)

    需要导入的jar包 具体实现 public class ColumnToString { public static void main(String[] args) { new ColumnToSt ...

  5. 正则表达式(三):Unicode诸问题下篇(转)

    原文:http://www.infoq.com/cn/news/2011/04/regular-expressions-4 我们使用正则表达式,熟练掌握各种功能和结构只是手段,解决实际的问题才是真正的 ...

  6. JAVA包装类介绍(一)(包装类、基本类型数据)

     1. 包装类把基本类型数据转换为对象      1.1每个基本类型在java.lang包中都有一个相应的包装类  2.包装类有何作用 2.1 提供了一系列实用的方法 2.2集合不允许存放基本数据类型 ...

  7. ASP.NET一个页面的生命周期

    在学习ASP.NET页面生命周期前,需要先了解之前的ASP.NET的基本运行机制,在理解ASP.NET基本运行机制原理后,下面将介绍ASP.NET的生命周期中,页面从创建到处理结束的过程中ASP.NE ...

  8. PHP 常用命令行

    1.PHP运行指定文件 php -f test.php (-f 可省略) 2.命令行直接运行PHP代码 php -r "phpinfo();" 如果结果太长,还可以 php -r ...

  9. 高性能mysql 第1,2,3章。

    一: 第一章 1:使用事务 start transaction; select * from t1; commit; 2:查看事务状态 mysql> show variables like 'a ...

  10. [vue]v-bind: sytle/class-bind&属性值绑定

    v-bind - style绑定 - class绑定 - 属性值绑定 <!DOCTYPE html> <html lang="en"> <head&g ...