算法模板——线段树8 (字符串回文变换)
2015-02-16 00:04
148 查看
实现功能:输入一个长度为N的由26个大写字母组成的字符串,输入M条指令:"1 x y",将x到y的字串重组构成一个字典序最小的回文串,如果不能构成回文串输出False,否则True并完成变换;"2 x y"输出从x到y的子串;"3 x y t"将x到y的所有字全部变成chr(t+64)(即对应大写字母)
原理:用一个数组维护字母个数即可,然后再附带一个带tag的区间覆盖操作,实现回文串的重组
原理:用一个数组维护字母个数即可,然后再附带一个带tag的区间覆盖操作,实现回文串的重组
type vec=array[0..26] of longint; var i,j,k,l,m,n,t:longint; a:array[0..500000] of vec; b:array[0..500000] of longint; c:array[0..500000] of ansistring; function empty:vec;inline; var a1:vec; begin fillchar(a1,sizeof(a1),0); exit(a1); end; function merge(a1,a2:vec):vec;inline; var i:longint; begin for i:=1 to 26 do a1[i]:=a1[i]+a2[i]; exit(a1); end; function max(x,y:longint):longint;inline; begin if x>y then max:=x else max:=y; end; function min(x,y:longint):longint;inline; begin if x<y then min:=x else min:=y; end; function strr(x:longint;y:char):ansistring;inline; var s1:ansistring;i:longint; begin s1:=''; for i:=1 to x do s1:=s1+y; exit(s1); end; procedure ext(z,x,y:longint);inline; begin if b[z]=0 then exit; if (x<>y) then begin b[z*2]:=b[z]; a[z*2]:=empty; a[z*2][b[z*2]]:=(x+y) div 2-x+1; c[z*2]:=strr((x+y) div 2-x+1,chr(b[z]+64)); b[z*2+1]:=b[z]; a[z*2+1]:=empty; a[z*2+1][b[z*2+1]]:=y-(x+y) div 2; c[z*2+1]:=strr(y-(x+y) div 2,chr(b[z]+64)); end; a[z]:=empty; a[z][b[z]]:=y-x+1; c[z]:=strr(y-x+1,chr(b[z]+64)); b[z]:=0; end; procedure built(z,x,y:longint); var c1:char; begin if x=y then begin read(c1);c1:=upcase(c1);c[z]:=c1; a[z]:=empty;a[z][ord(c1)-64]:=1; end else begin built(z*2,x,(x+y) div 2); built(z*2+1,(x+y) div 2+1,y); c[z]:=c[z*2]+c[z*2+1]; a[z]:=merge(a[z*2],a[z*2+1]); end; b[z]:=0; end; function getsum(z,x,y,l,r:longint):vec; var a1:vec; begin if l>r then exit(empty); if b[z]>0 then begin a1:=empty; a1[b[z]]:=r-l+1; exit(a1); end; if (x=l) and (y=r) then exit(a[z]); getsum:=merge(getsum(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2)),getsum(z*2+1,(x+y) div 2+1,y,max((x+y) div 2+1,l),r)); end; procedure cover(z,x,y,l,r,t:longint); begin if l>r then exit; if (x=l) and (y=r) then begin b[z]:=t; a[z]:=empty;a[z][b[z]]:=r-l+1; c[z]:=strr(r-l+1,chr(64+b[z])); exit; end; ext(z,x,y); cover(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2),t); cover(z*2+1,(x+y) div 2+1,y,max((x+y) div 2+1,l),r,t); c[z]:=c[z*2]+c[z*2+1]; a[z]:=merge(a[z*2],a[z*2+1]); end; function setup(x,y:longint):boolean; var a1:vec;i,j,k,l:longint; begin a1:=getsum(1,1,n,x,y); l:=0; for i:=1 to 26 do if odd(a1[i]) then if l=0 then l:=i else exit(false); j:=x;k:=y; for i:=1 to 26 do begin cover(1,1,n,j,j+a1[i] div 2-1,i); cover(1,1,n,k-a1[i] div 2+1,k,i); j:=j+a1[i] div 2;k:=k-a1[i] div 2; end; if l>0 then cover(1,1,n,j,k,l); exit(true); end; function getstr(z,x,y,l,r:longint):ansistring;inline; begin if l>r then exit(''); if b[z]>0 then exit(strr(r-l+1,chr(b[z]+64))); if (x=l) and (y=r) then exit(c[z]); exit(getstr(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2))+getstr(z*2+1,(x+y) div 2+1,y,max((x+y) div 2+1,l),r)); end; begin readln(n,m); built(1,1,n); readln; for i:=1 to m do begin read(t); case t of 1:begin readln(j,k); writeln(setup(j,k)); end; 2:begin readln(j,k); writeln(getstr(1,1,n,j,k)); end; 3:begin readln(j,k,l); cover(1,1,n,j,k,l); end; end; end; end.
相关文章推荐
- 妙趣横生算法 4:判断字符串是否回文
- 最大算法【Manacher模板】HDU 3068——求最长回文子串
- 最长回文子串模板---Manacher算法。时间复杂度O(N)
- Girls' research(已完善的Manacher算法模板:输出最长回文子串)
- Manacher算法-求字符串中最长回文串
- 每天一道算法题1 判断字符串是否是回文字符串或者是否含有回文字符子串
- 最长回文---hdu3068 (回文串 manacher 算法模板)
- 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串
- Manacher算法:求解最长回文字符串,时间复杂度为O(N)
- 【模板】字符串算法-字符串最小表示法
- Manacher算法处理字符串回文
- 【算法】寻找字符串中最长的回文序列
- 笔试——字符串算法题——寻找最大回文子串
- ] 找工作知识储备(2)---数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串
- 数据结构——算法之(005)(判断字符串是否是对称的即(回文字符串))
- 串子串Manacher算法: O(n)时间求字符串的最长回文子串
- 找工作知识储备---数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串
- 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串
- 算法:判断字符串是否是回文的
- 算法基础——判断一个字符串至多添加一个字符之后是否回文