HOJ 13830 DNA Sequencing
Problem description |
Finally, Plankton’s attempts to steal the Krabby Patty formula succeeded and it eventually put the Krusty Krab out of business. So, SpongeBob and his co-workers decided to switch to a brand new job. Their new startup is Krusty-Royan, a biological research institute whose main focus is on DNA sequencing. Their first customer is Sandy, the squirrel scientist, who has found the corpse of an alien from the outer space and asked Krusty-Royan crew to extract its DNA sequence. Contrary to the life on earth, the DNA of the alien was not only composed of the 4 well-known nucleotides (A, C, G, and T), but all 26 English letters! So, each part of its DNA is a sequence of capital English letters. Given the alien tissue, the DNA sequencer machine extracted a number of (not necessarily distinct) DNA sequences and printed them on paper, one per line. Based on the contract, a DNA sequence is valid only if its length is at least M, and Sandy will pay one dollar for each distinct valid DNA sequence. So, Mr. Krabs, the greedy boss of Krusty-Royan has asked SpongeBob to use a correction pen and erase some letters from the end of the sequences printed on the paper in order to maximize the number of distinct valid DNA sequences. Your job is to help SpongeBob find the maximum number of distinct valid DNA sequences he can make. |
Input |
There are multiple test cases in the input. Each test case starts with a line containing two space-separated integers k and M (1 ⩽ k ⩽ 500; 1 ⩽ M ⩽ 500). Each of the next k lines starts with a number ni followed by a string si which means there are ni copies of DNA sequence si printed on the paper (1 ⩽ ni ⩽ 500). The length of the strings is a positive integer not greater than 500. The input terminates with a line containing 0 0 which should not be processed as a test case. |
Output |
For each test case, output a line containing the maximum number of distinct valid DNA sequences which SpongeBob can provide. |
Sample Input |
2 1 2 ABB 2 ABC 2 2 2 ABB 2 ABC 2 3 2 ABB 2 ABC 2 4 2 ABB 2 ABC 0 0 |
Sample Output |
4 3 2 0 |
思路:字典树,可能会哈希的大佬可以哈希过,不熟的孩子,冲突啊冲突
这里建树的时候节点有两个元素,一个height目的是为了判断从根节点到这个子串是否合法,一个num表示这个子串我是否需要,同时满足就是我要的子串,累加上去就好;
这里给出队友和老师代码:
#include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const int maxn=250020; struct node { int num,height,ch[26]; void init(){num=height=0;memset(ch,0,sizeof ch);} }; node tre[maxn]; int cnt=1;//节点下标 const int root=1;//根节点 void insert(int cur,const string &s,int i,int m,int Size) { int id=s[i]-'A'; if(tre[cur].ch[id]==0)tre[cur].ch[id]=++cnt; int ch=tre[cur].ch[id];//子节点 tre[ch].height=i; if(Size==i+1)tre[ch].num+=m;//字符串全部插入,更新num else insert(ch,s,i+1,m,Size); } int dfs(int cur,int h) { int res=0; for(int i=0;i<26;i++) { if(tre[cur].ch[i]!=0) { int ch=tre[cur].ch[i]; res+=dfs(ch,h); tre[cur].num+=max(tre[ch].num-1,0); } } if(tre[cur].height+1>=h&&tre[cur].num>0)res++;//既符合要求,又是我需要的子串; return res; } char s[510]; int main() { freopen("input.txt","r",stdin); int n,k,m; while(scanf("%d%d",&n,&k),n) { cnt=1; for(int i=0;i<maxn;i++) tre[i].init(); for(int i=0;i<n;i++) { scanf("%d%s",&m,s); int Size=strlen(s); insert(root,s,0,m,Size); } tre[root].height=-1; printf("%d\n",dfs(root,k)); } return 0; }