zoukankan      html  css  js  c++  java
  • 【URAL 1989】 Subpalindromes(线段树维护哈希)

    Description


    You have a string and queries of two types:
    replace i’th character of the string by character a;
    check if substring sj...sk is a palindrome.

    Input


    The first line contains a string consisting of n small English letters. The second line contains an integer m that is the number of queries (5 ≤ n, m ≤ 105). The next m lines contain the queries.
    Each query has either form “change i a”, or “palindrome? j k”, where i, j, k are integers (1 ≤ i ≤ n; 1 ≤ j ≤ k ≤ n), and character a is a small English letter.

    Output


    To all second type queries, you should output “Yes” on a single line if substring sj...sk is a palindrome and “No” otherwise.

    Sample input

    abcda
    5
    palindrome? 1 5
    palindrome? 1 1
    change 4 b
    palindrome? 1 5
    palindrome? 2 4
    

    Sample onput

    No
    Yes
    Yes
    Yes
    

    题解

    使用线段树维护哈希值。
    滚动哈希即rabin-karp
    原hash:
    (ha[i]=ha[i-1] imes seed+s[i])
    可以预处理出seed进位:
    (p[i]=p[i-1] imes seed)
    这样每个位置的哈希值可以直接算出。
    如果要改变某个位置的字符,那么原hash值变成
    (ha[i]=p[i-1] imes ch)
    这样的hash计算无需滚动,因为计算出了进位,每一位是直接算出的。那么可以直接合并两个区间的哈希值,
    即:
    ha[rt]=ha[rt<<1]+ha[rt<<1|1]
    改变也是单调修改,这些都是线段树的经典应用

    import java.io.*;
    import java.util.*;
    
    public class Main {
    	static final int N = (int)1e5+10;
    	//static final long MOD=(int)1e18+7;
    	static final int inf = 0x3f3f3f3f;
    	static char a[]=new char[N];
    	static long p[]=new long[N];
    	static long ha[]=new long[N];
    	static long sum[][]=new long[2][N<<2];
    	static void Init(int n) {
    		int seed=123;
    		p[0]=1;
    		for(int i=1;i<=n;i++) p[i]=(p[i-1]*seed);
    	}
    	static void PushUp(int rt,int flag) {
    		sum[flag][rt]=(sum[flag][rt<<1]+sum[flag][rt<<1|1]);
    	}
    	static void Build(int rt,int l,int r,int flag) {
    		if(l==r) {
    		      sum[flag][rt]=ha[l];
    		      return;
    		}
    		int mid=(l+r)>>1;
    	    Build(rt<<1,l,mid,flag);
    	    Build(rt<<1|1,mid+1,r,flag);
    	    PushUp(rt,flag);
    	}
    	static void update(int a,long b,int rt,int l,int r,int flag) {
    		if(l==r) {
    			sum[flag][rt]=b;
    			return;
    		}
    		int mid=(l+r)>>1;
    	    if(a<=mid) update(a,b,rt<<1,l,mid,flag);
    	    if(a>mid) update(a,b,rt<<1|1,mid+1,r,flag);
    	    PushUp(rt,flag);
    	}
    	static long query(int a,int b,int rt,int l,int r,int flag) {
    		if(a<=l&&r<=b) {
    			return sum[flag][rt];
    		}
    		int mid=(l+r)>>1;
    	    long res=0;
    	    if(a<=mid) res=(res+query(a,b,rt<<1,l,mid,flag));
    	    if(b>mid) res=(res+query(a,b,rt<<1|1,mid+1,r,flag));
    	    return res;
    	}
    	public static void main(String[] args) {
    		InputStream sysi = System.in;
    		OutputStream syso = System.out;
    		InputReader in = new InputReader(sysi);
    		PrintWriter out = new PrintWriter(syso);
    		a=in.next().toCharArray();
    		int m=in.nextInt();
    		int s,e,s1,e1,n=a.length;char ch;
    		Init(n);
    		for(int i=0;i<n;i++) ha[i+1]=((long)a[i]*p[i]);
    		Build(1,1,n,0);
    		char tmp;
    		for(int i=0;i<n/2;i++) {
    			tmp=a[i];a[i]=a[n-i-1];
    			a[n-i-1]=tmp;
    		}
    		for(int i=0;i<n;i++) ha[i+1]=((long)a[i]*p[i]);
    		Build(1,1,n,1);String str;
    		while(m--!=0) {
    		     if(in.next().equals("palindrome?")) {
    		    	  s=in.nextInt();e=in.nextInt();
    		    	  long ha1=query(s,e,1,1,n,0);
    		    	  s1=n+1-e;e1=n+1-s;
    		    	  long ha2=query(s1,e1,1,1,n,1);
    		    	  if(s1>s) ha1=(ha1*p[s1-s]);
    		    	  else ha2=(ha2*p[s-s1]);
    		    	  if(ha1==ha2) out.println("Yes");
    		    	  else out.println("No");
    		     }else {
    		    	  s=in.nextInt();str=in.next();
    		    	  ch=str.charAt(0);
    		    	  update(s,p[s-1]*ch,1,1,n,0);
    		    	  update(n+1-s,p[n-s]*ch,1,1,n,1);
    		     }
    		     out.flush();
    		}
    		out.close();
    	}
    
    	static class InputReader {
    		public BufferedReader reader;
    		public StringTokenizer tokenizer;
    
    		public InputReader(InputStream stream) {
    			reader = new BufferedReader(new InputStreamReader(stream), 32768);
    			tokenizer = null;
    		}
    
    		public String next() {
    			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
    				try {
    					tokenizer = new StringTokenizer(reader.readLine());
    				} catch (IOException e) {
    					throw new RuntimeException(e);
    				}
    			}
    			return tokenizer.nextToken();
    		}
    
    		public int nextInt() {
    			return Integer.parseInt(next());
    		}
    	}
    }
    
  • 相关阅读:
    react-当前的时:分:秒-每秒更新
    一键回顶部按钮 HTML+CSS+JS+jQuery完成
    JavaScript-浏览器的三种弹窗方式
    网页计算器简单实现加减乘除功能
    Oracle -- 记一次ADG库迁移过程小结 -- 上篇(ADG建库)
    expression解决IE6下固定定位的兼容
    Css攻克Selectors 一
    昨天开通了博客,希望自己争取早点写出东西
    Static关键字的用法
    XSHELL使用教程
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/7504589.html
Copyright © 2011-2022 走看看