SGU 505 Prefixes and suffixes
题解 现将字符串排序; 那么某前缀在字符串中出现肯定是连续的;写几个案例就知道了;这是记录每个字符在以前缀排名的rank ; 然后将字符串反序; 再排序;依照前缀,可以知道相同名字的后缀也会出现在一段排序好的连续的字符串里面;这样得到前缀的区间为 [a,b], [c,d]; 只要统计每个字符是否在 a 到 b 之间; 同时满足在 c 到 d 之间; 获取某个前缀的第一个匹配段字符串 和 最后一个字符串也就是 [a,b] 使用了字典树搞; 然后 再用线段树保留最大值和最小值;竟然没有超时, 啊,,哈哈;
#include<iostream> #include<stdio.h> #include<cstring> #include<algorithm> #include<cmath> #include<string> #include<vector> using namespace std; struct date{ int sta,end; date *next[27]; }*root,*rot,tree[412345]; int total; date *creat_node(){ for( int i = 0; i < 27; i++ ) tree[total].next[i] = NULL; tree[total].sta = -1; tree[total].end = -1; return &tree[total++]; } void inint( ){ total = 0; root = creat_node(); rot = creat_node(); } void insert( string &word,int i,int tab ) { date *p; int len = word.length(); if( tab )p = root; else p = rot; for( int j = 0; j < len; j++ ) { int num = word[j] - 'a'; if( p->next[num] == NULL ) { p->next[num] = creat_node(); p->next[num]->sta = i; } p->next[num]->end = i; p = p->next[num]; } } int sta,en; void work( string &word,int tab ) { date *p; int len = word.length(); if( tab ) p = root; else p = rot; for( int j = 0; j < len; j++ ) { int num = word[j] - 'a'; if( p->next[num] == NULL ){ sta = -1; en = -1; return; } p = p->next[num]; sta = p->sta; en = p->end; } } struct DAte{ string sss; int pos; bool operator <(const DAte &a )const{ return sss < a.sss; } }arr[1123456]; struct Date{ int lt,rt,Max,Min,num; }node[1123456]; void build( int lt,int rt,int t ){ node[t].lt = lt; node[t].rt = rt; if( lt == rt ){ node[t].num = 1; node[t].Max = node[t].Min = arr[lt].pos; return; } int mid = ( lt+rt )>>1; build( lt,mid,t<<1 ); build( mid+1,rt,t<<1|1 ); node[t].Max = max( node[t<<1].Max,node[t<<1|1].Max ); node[t].Min = min( node[t<<1].Min,node[t<<1|1].Min ); node[t].num = node[t<<1].num+node[t<<1|1].num; } int query( int lt,int rt,int a,int b,int t ) { if( node[t].Min > b || node[t].Max < a )return 0; int mid = ( node[t].lt+node[t].rt )>>1; if( node[t].lt == lt && node[t].rt == rt ) { if( node[t].Max <= b && node[t].Min >= a )return node[t].num; return query( lt,mid,a,b,t<<1 ) + query( mid+1,rt,a,b,t<<1|1 ); } if( node[t<<1].rt >= rt )return query( lt,rt,a,b,t<<1 ); else if( node[t<<1|1].lt <= lt )return query( lt,rt,a,b,t<<1|1 ); else return query(lt,mid,a,b,t<<1)+query(mid+1,rt,a,b,t<<1|1); } int main( ) { int N,M; string str; while( scanf("%d",&N) != EOF ) { for( int i = 0; i < N; i++ )cin>>arr[i].sss; sort(arr,arr+N); inint(); for( int i = 0; i < N; i++ ) arr[i].pos = i; for( int i = 0; i < N; i++ ) insert(arr[i].sss,i,1 ); for( int i = 0; i < N; i++ ) reverse(arr[i].sss.begin(),arr[i].sss.end()); sort(arr,arr+N); build(0,N-1,1); for( int i = 0; i < N; i++ ) insert(arr[i].sss,i,0); scanf("%d",&M); for( int i = 1; i <= M; i++ ){ cin>>str; work(str,1); int a = sta,c = en; cin>>str; reverse(str.begin(),str.end());work(str,0); int b = sta,d = en; if( a == -1 || b == -1 )cout<<0<<endl; else cout<<query( b,d,a,c,1 )<<endl; } } return 0; } /* 14 abasbssbs sfasffsd adfsas fdsssf safas fsadf fases sdesas aesdf sefss aseesaes fdsasesa seasea sedfsas 11 a a ab ac fa a fa s ac ca fd sa fd as se sa fs fd fd fs ab sb */