记录编号 85246 评测结果 AAAAAAAAAA
题目名称 [SPOJ 1676]文本生成器 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.020 s
提交时间 2013-12-30 20:08:51 内存使用 0.31 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<iomanip>
using namespace std;
typedef unsigned ll;
const ll MOD=10007;
const int SIZEN=11;
const int SIZES=62;
string dict[SIZEN];
int stpos[SIZEN]={0};//字符串的状态编号起点
int maxmatch[SIZEN]={0};//每个单词有意义状态的最大下标
int N,SNUM;//SNUM为状态数
int L;
pair<int,int> state[SIZES];//将所有"某个单词的某个前缀"压缩成一维.state[i]的first储存在dict中的下标,second储存在字符串中的下标,特别的1为空串
class MATRIX{
public:
	int n,m;//n行m列
	ll s[SIZES][SIZES];
	MATRIX(){//初始化为零
		m=n=0;
		memset(s,0,sizeof(s));
	}
	void print(void){//调试接口,输出矩阵
		cout<<"size:"<<n<<" "<<m<<endl;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++) cout<<s[i][j]<<" ";
			cout<<endl;
		}
	}
	void assign_one(int sn){//赋值为sn行的单位矩阵
		n=m=sn;
		for(int i=1;i<=n;i++) s[i][i]=1;
	}
};
MATRIX operator * (MATRIX a,MATRIX b){//矩阵乘法,结果对MOD取模
	MATRIX c;
	c.n=a.n;c.m=b.m;
	int i,j,k;
	for(i=1;i<=c.n;i++){
		for(j=1;j<=c.m;j++){
			c.s[i][j]=0;
			for(k=1;k<=a.m;k++){
				c.s[i][j]+=(a.s[i][k]*b.s[k][j]);
			}
			c.s[i][j]%=MOD;
		}
	}
	return c;
}
MATRIX quickpow(MATRIX a,ll n,int sn){//a^n,sn行/列
	MATRIX ans;ans.assign_one(sn);
	while(n){
		if(n&1) ans=ans*a;
		a=a*a;
		n>>=1;
	}
	return ans;
}
ll quickpow(ll x,ll y){//x^y%MOD
	ll ans=1;
	ll temp=x;
	while(y){
		if(y&1) ans=ans*temp%MOD;//奇数
		temp=temp*temp%MOD;
		y>>=1;
	}
	return ans;
}
int pairpos(pair<int,int> p){//第x个字符串下标为y的状态编号
	return stpos[p.first]+p.second;
}
int findprefix(string str,int k){//得到str长度为k的后缀是哪个单词的前缀
	int start,i,j;
	start=str.size()-k;
	for(i=1;i<=N;i++){
		if(dict[i].size()<k) continue;
		for(j=0;j<k;j++) if(str[start+j]!=dict[i][j]) goto NEXT;
		if(j==dict[i].size()||j-1>maxmatch[i]) return -1;//单词被完全匹配
		return i;
		NEXT:;
	}
	return 0;//若无合适的前缀就是第0号单词(空串)
}
int match(string str){//得到"最大匹配"的标号
	pair<int,int> ans=make_pair(0,0);//first是单词,second是到第几个下标
	int i,j;
	bool flag=false;
	for(i=str.size();i>=1;i--){
		j=findprefix(str,i);
		if(j==-1) return 0;//完全匹配,无效
		if(j){
			ans=make_pair(j,i-1);
			break;
		}
	}
	return pairpos(ans);
}
bool read(void){
	if(scanf("%d%d",&N,&L)==EOF) return false;
	int i;
	for(i=1;i<=N;i++) cin>>dict[i];
	return true;
}
void init(MATRIX &G,MATRIX &D){
	int i,j,k,t,st,tot=1;
	string str;
	state[tot]=make_pair(0,-1),stpos[0]=tot,maxmatch[0]=-1;
	dict[0]="\0";
	for(i=1;i<=N;i++){
		stpos[i]=tot+1;
		str="\0";
		maxmatch[i]=dict[i].size()-2;//若没有其他因素,一直到'少一个'都是有意义的状态
		for(j=0;j<dict[i].size()-1;j++){//不能出现完全匹配某单词的状态
			str+=dict[i][j];
			for(k=1;k<=N;k++){
				for(t=0;t<dict[k].size();t++){
					if(dict[k][dict[k].size()-1-t]!=str[str.size()-1-t]) break;
				}
				if(t==dict[k].size()){
					maxmatch[i]=j-1;
					goto NEXT;
				}
			}
			state[++tot]=make_pair(i,j);
		}
		NEXT:;
	}
	SNUM=tot;
	G.n=1,G.m=SNUM;
	for(i=1;i<=SNUM;i++) G.s[1][i]=1;//初始化了G
	D.n=D.m=SNUM;
	for(i=1;i<=SNUM;i++){
		str="\0";
		for(j=0;j<=state[i].second;j++) str+=dict[state[i].first][j];
		for(j=0;j<26;j++){//枚举26个字母
			k=match(str+char(j+'A'));
			if(k) D.s[k][i]++;
		}
	}
}
void work(void){
	MATRIX G,D;//G是状态矩阵,D是转移矩阵
	init(G,D);
	G=G*quickpow(D,L,SNUM);
	ll ans=quickpow(26,L)-G.s[1][1];
	cout<<(ans+MOD)%MOD<<endl;
}
int main(){
	freopen("textgen.in","r",stdin);
	freopen("textgen.out","w",stdout);
	while(read()) work();
	return 0;
}