第一次做HN省选有点激动 呸,04年的简单板子题有什么可激动的,还WA了一次难道不羞愧嘛...
好滴不闲扯直接来港
顺便就做trie树滴学习笔记辽 就是懒怎么的,理直气壮.JPG
正解:trie树+dp
解题报告:
其实trie树还挺基础的,之前也学过,但是一直没有落实,就一直觉得掌握得也一般,刚好今天想着落实一下字符串,就把trie树kmp都搞掉算了quq
然后就跑去做了道trie树的板子题quq
首先trie树的概念我就不想讲了,也太简单了?就放下基本架构quq
struct trie{bool end;int nex[30];trie(){end=0;rp(i,0,29)nex[i]=0;}}tr[MAXtre]; /*定义:end:该位能否作为结尾 nex:这一位后面的那个字母的位置*/ inline void build(string x,int y) { int now=0,cjk=0; while(cjk<y) { if(!tr[now].nex[x[cjk]-'a'+1]){tr[now].nex[x[cjk]-'a'+1]=++cnt;} now=tr[now].nex[x[cjk]-'a'+1];++cjk; } tr[now].end=1; } //没什么可说的,唯一有提及的意义的一点是拿了学长的名字做变量名,听说这样可以RP++题目更容易A掉暴力骗到的分更多哦(假的x //哦对了那个y是我顺手算好了x的长度了就直接放函数里了,平时实现的时候不放也是没关系dei
然后这题的话,除了trie树还要个巨简单的dp
就是开个bool数组f[i]存第i位能否用字典树上的表示出来
然后如果可以表示我们就可以把它往后找 找到一个end 它end的那个点就也可以就赋成1(和之前dp题单boss里最后一题思想差不多?只是麻烦些趴
然后大力转移最后从后往前找哪一位可以是1就输出,over
好放代码,放了代码我就去学kmp了!
#include<bits/stdc++.h> using namespace std; #define rp(i,x,y) for(register int i=x;i<=y;++i) const int MAXtre=200+5; int n,m,cnt;bool f[1000010]; struct trie{bool end;int nex[30];trie(){end=0;rp(i,0,29)nex[i]=0;}}tr[MAXtre]; inline int read() { char ch=getchar();int x=0;bool y=1; while(ch!='-' && (ch<'0' || ch>'9'))ch=getchar(); if(ch=='-')ch=getchar(),y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar(); return y?x:-x; } inline void build(string x,int y) { int now=0,cjk=0; while(cjk<y) { if(!tr[now].nex[x[cjk]-'a'+1]){tr[now].nex[x[cjk]-'a'+1]=++cnt;} now=tr[now].nex[x[cjk]-'a'+1];++cjk; } tr[now].end=1; } void solve(string s) { s=' '+s;int ls=s.length(); memset(f,0,ls+1);f[0]=1; for(int i=0; i<ls; ++i) if(f[i]) { int cjk=i+1,now=0; while(cjk<=ls) { now=tr[now].nex[s[cjk]-'a'+1]; if(tr[now].end)f[cjk]=1;++cjk; if(now==0)cjk=ls+1; } } for(int i=ls;i>=0;--i)if(f[i]){printf("%d\n",i);return;} } int main() { n=read();m=read(); rp(i,1,n) { string t;cin>>t; build(t,t.length()); } rp(i,1,m) { string t;cin>>t; solve(t); } return 0; }