标签:img nsis 答案 begin mod fill 问题 字母 字符串
题意:求一个字符串的最长回文子串
n<=1000
思路:这是一道论文题
需要注意的细节:
1.奇偶分类
2.中间的分割符与最后的附加字母都是最小值,但两者不能相同,否则height可能会出现问题
答案即为min(height[rank[x]+1]...height[rank[y]])
1 var f:array[0..3000,0..11]of longint; 2 x,y,sa,rank,height,a,wc,wd:array[0..3000]of longint; 3 ch:ansistring; 4 n,m,i,k,max,tmp,t,j:longint; 5 6 function min(x,y:longint):longint; 7 begin 8 if x<y then exit(x); 9 exit(y); 10 end; 11 12 procedure swap(var x,y:longint); 13 var t:longint; 14 begin 15 t:=x; x:=y; y:=t; 16 end; 17 18 function cmp(a,b,l:longint):boolean; 19 begin 20 exit((y[a]=y[b])and(y[a+l]=y[b+l])); 21 end; 22 23 procedure getsa(n:longint); 24 var i,j,p:longint; 25 begin 26 for i:=0 to n-1 do 27 begin 28 x[i]:=a[i]; 29 inc(wc[a[i]]); 30 end; 31 for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i]; 32 for i:=n-1 downto 0 do 33 begin 34 dec(wc[x[i]]); 35 sa[wc[x[i]]]:=i; 36 end; 37 j:=1; p:=1; 38 while p<n do 39 begin 40 p:=0; 41 for i:=n-j to n-1 do 42 begin 43 y[p]:=i; inc(p); 44 end; 45 for i:=0 to n-1 do 46 if sa[i]>=j then begin y[p]:=sa[i]-j; inc(p); end; 47 for i:=0 to n-1 do wd[i]:=x[y[i]]; 48 for i:=0 to m-1 do wc[i]:=0; 49 for i:=0 to n-1 do inc(wc[wd[i]]); 50 for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i]; 51 for i:=n-1 downto 0 do 52 begin 53 dec(wc[wd[i]]); 54 sa[wc[wd[i]]]:=y[i]; 55 end; 56 for i:=0 to n do swap(x[i],y[i]); 57 p:=1; x[sa[0]]:=0; 58 for i:=1 to n-1 do 59 if cmp(sa[i-1],sa[i],j) then x[sa[i]]:=p-1 60 else begin x[sa[i]]:=p; inc(p); end; 61 j:=j*2; 62 m:=p; 63 end; 64 end; 65 66 procedure getheight(n:longint); 67 var i,j,k:longint; 68 begin 69 k:=0; 70 for i:=1 to n do rank[sa[i]]:=i; 71 for i:=0 to n-1 do 72 begin 73 if k>0 then dec(k); 74 j:=sa[rank[i]-1]; 75 while a[i+k]=a[j+k] do inc(k); 76 height[rank[i]]:=k; 77 end; 78 end; 79 80 function query(x,y:longint):longint; 81 var len,l:longint; 82 begin 83 len:=y-x+1; l:=trunc(ln(len)/ln(2)); 84 exit(min(f[x,l],f[y-(1<<l)+1,l])); 85 end; 86 87 function lcp(x,y:longint):longint; 88 var i,j:longint; 89 begin 90 //inc(x); inc(y); 91 i:=rank[x]; j:=rank[y]; 92 if i>j then swap(i,j); 93 inc(i); 94 exit(query(i,j)); 95 end; 96 97 procedure init; 98 begin 99 fillchar(a,sizeof(a),0); 100 fillchar(height,sizeof(height),0); 101 fillchar(sa,sizeof(sa),0); 102 fillchar(rank,sizeof(rank),0); 103 fillchar(f,sizeof(f),0); 104 fillchar(x,sizeof(x),0); 105 fillchar(y,sizeof(y),0); 106 fillchar(wc,sizeof(wc),0); 107 fillchar(wd,sizeof(wd),0); 108 end; 109 110 begin 111 assign(input,‘ural1297.in‘); reset(input); 112 assign(output,‘ural1297.out‘); rewrite(output); 113 while not eof do 114 begin 115 init; 116 readln(ch); 117 n:=length(ch); 118 if n=0 then break; 119 for i:=0 to n-1 do a[i]:=ord(ch[i+1]); 120 a[n]:=1; m:=300; 121 for i:=n+1 to 2*n do a[i]:=ord(ch[n-(i-n)+1]); 122 a[n*2+1]:=0; 123 getsa(n*2+2); 124 getheight(n*2+1); 125 m:=n*2+2; 126 t:=trunc(ln(m)/ln(2)); 127 for i:=2 to m do f[i,0]:=height[i]; 128 for i:=1 to t do 129 for j:=2 to m do 130 if j+(1<<(i-1))<=m then f[j,i]:=min(f[j,i-1],f[j+(1<<(i-1)),i-1]); 131 max:=0; k:=0; 132 for i:=0 to n-1 do 133 begin 134 tmp:=lcp(i,2*n-i)*2-1; 135 if tmp>max then 136 begin 137 max:=tmp; 138 k:=i; 139 end; 140 if i>0 then 141 begin 142 tmp:=lcp(i,n*2-i+1)*2; 143 if tmp>max then 144 begin 145 max:=tmp; 146 k:=i; 147 end; 148 end; 149 end; 150 if max mod 2=1 then 151 for j:=k-max div 2+1 to k+max div 2+1 do write(ch[j]) 152 else 153 for j:=k-max div 2+1 to k+max div 2 do write(ch[j]); 154 writeln; 155 // for i:=2 to n*2+2 do writeln(height[i]); 156 // for i:=1 to n*2+2 do writeln(rank[i]); 157 // writeln; 158 end; 159 160 161 162 close(input); 163 close(output); 164 end.
标签:img nsis 答案 begin mod fill 问题 字母 字符串
原文地址:http://www.cnblogs.com/myx12345/p/6418041.html