effect
Look at the following questions:
1. Give n words and m questions, one word at a time, and answer whether the word has appeared in the word list.
Answer: simple! map, short and sharp.
2. Give n words and m questions, one prefix at a time, and answer the question how many words are prefixed.
Answer: map, take each word apart.
judge: n<=200000,TLE!
This requires a high-level data structure - Trie tree (dictionary tree)
concept
Word search tree, Trie tree, is a tree structure and a variant of hash tree.
advantage:
The common prefix of string is used to save storage space, minimize unnecessary string comparison, and the query efficiency is higher than that of hash table.
Data structure definition of Trie:
Take the lowercase dictionary tree as an example
#define MAX 26 / / change as needed}; typedef struct Trie { Trie *next[MAX]; int count;
next indicates the number of types in each layer, that is, the number of subtrees. The example is a lowercase letter, 26.
count indicates the number of identical prefixes in a dictionary tree.
operation
Generate dictionary tree:
Idea:
Scan the word from left to right. If the letter does not appear under the corresponding root node, insert the letter; Otherwise, go down the dictionary tree and look at the next letter of the word.
code:
void createTrie(char *str) { int len = strlen(str); Trie *p = root, *q; for(int i=0; i<len; ++i) { int id = str[i]-'0'; if(p->next[id] == NULL) { q = (Trie *)malloc(sizeof(Trie)); q->v = 1; //Initial v==1 for(int j=0; j<MAX; ++j) q->next[j] = NULL; p->next[id] = q; p = p->next[id]; } else { p->next[id]->v++; p = p->next[id]; } } p->v = -1; //If it is the end, change v to - 1 }
Use the tree to find:
Take finding out whether a prefix has ever appeared as an example
thinking
Scan each letter from left to right and look down the dictionary tree. You can find this letter and go down. Otherwise, the search ends, that is, there is no prefix; After the prefix is scanned, it indicates that there is this prefix.
code
int search(char *str) { int len = strlen(str); Trie *p = root; for(int i=0; i<len; ++i) { int id = str[i]-'0'; p = p->next[id]; if(p == NULL) //If it is an empty set, it means that there is no string with this prefix return 0; if(p->v == -1) //The existing string in the character set is the prefix of this string return -1; } return -1; //This string is the prefix of a string in the character set }
actual combat
Dictionary tree
Template question
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct ooo { int next[26]; bool mark; //sign }dd[505555]; int top,n,m; char a[20],b[20]; int creat() //Assign a new node { memset(dd[top].next,-1,sizeof(dd[top].next)); //Indicates pointing to null dd[top].mark=false;//Indicates that there is no corresponding string return top++; } int xiab(char c) { return c-'a'; //Corresponding subscript } void insert(int root,char *s) //Insert S into the dictionary tree { int i,len=strlen(s); for(i=0;i<len;i++) { if(dd[root].next[xiab(s[i])]==-1) dd[root].next[xiab(s[i])]=creat(); root=dd[root].next[xiab(s[i])]; } dd[root].mark=true; } bool search(int root,char *s) //Ask if it appears in the dictionary tree { for(int i=0;s[i]!='\0';i++) { if(dd[root].next[xiab(s[i])]==-1) return false; root=dd[root].next[xiab(s[i])]; } return dd[root].mark; } int main() { int i,j,root; while(scanf("%d %d",&n,&m)&&(n||m)) { top=0; root=creat(); for(i=0;i<n;i++) { scanf("%s",a); insert(root,a); } for(i=0;i<m;i++) { scanf("%s",b); printf("%s\n",search(root,b)?"Yes":"No"); } } return 0; }
Idea:
The title requires a suffix, which can be inverted into a prefix.
But If the amount of data is too large, the dictionary tree will time out, and the problem will become a thinking problem.
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; const int N=1e5+10; int col[N]; int a[N][15]; int flag[N]; int k; string s1,s2; void Insert() { int p=0,i; for(i=0;i<s1.size();i++) { if(!a[p][s1[i]-'0']) a[p][s1[i]-'0']=++k; col[p]++;//Record a few words passed by him. p=a[p][s1[i]-'0']; } flag[p]=1;//Indicates that this is the end of a word. } int search1() { int p=0,i; for(i=0;i<s2.size();i++) { if(!a[p][s2[i]-'0']) return 0; p=a[p][s2[i]-'0']; } return col[p]; } int main() { int n,m,i; ios::sync_with_stdio(false); while(cin>>n) { for(i=1;i<=n;i++) { cin>>s1; reverse(s1.begin(),s1.end()); Insert(); } cin>>m; for(i=1;i<=m;i++) { cin>>s2; reverse(s2.begin(),s2.end()); int num=search1();//Find the word segment and return the value. printf("%d\n",num); } memset(flag,0,sizeof(flag)); memset(a,0,sizeof(a)); memset(col,0,sizeof(col)); k=0;//initialization. } return 0; }