zoukankan      html  css  js  c++  java
  • [THUPC2018] 绿绿和串串

    题目

    水题,就当复习马拉车了;

    (vis_i)表示前缀(i)能否变换成功;

    如果前缀(i)进行一次对称变换,长度为(i+i-1);当(i+i-1>n)的时候,我们只需要判断回文半径是否不小于(n-i)即可;

    (i=i-1leq n)时,如果进行变换后得到的是前缀(i+i-1),那么(vis_i=vis_{i+i-1}),否则(vis_i=0);

    于是我们只要判断(i)进行对称变换后是否为(i+i-1),这相当于问(i)的回文半径是否为(i-1),马拉车即可;

    代码

    #include<bits/stdc++.h>
    #define re register
    #define min(a,b) ((a)<(b)?(a):(b))
    const int maxn=1e6+5;int n;
    int vis[maxn],r[maxn];char S[maxn];
    int main() {
    	int T;scanf("%d",&T);
    	for(;T;--T) {
    		scanf("%s",S+1);n=strlen(S+1);vis[n]=1;
    		int R=1,mid=1;for(re int i=1;i<=n;i++)r[i]=0;
    		for(re int i=1;i<=n;i++) {
    			if(i<=R)r[i]=min(R-i,r[(mid<<1)-i]);
    			for(re int j=r[i]+1;j<=i&&j<=n&&S[i+j]==S[i-j];++j)r[i]=j;
    			if(i+r[i]>R)R=i+r[i],mid=i;
            }
    		for(re int i=n-1;i>1;i--) {
    			if(i+i-1>n) {vis[i]=(r[i]>=n-i);continue;}
    			vis[i]=(r[i]>=i-1)&vis[i+i-1];
    		}
    		for(re int i=1;i<=n;i++)if(vis[i])printf("%d%c",i,(i==n)?'
    ':' '),vis[i]=0;
    	}
    }
    //g++ lg5446.cpp -o lg5446 -O2 -lm -std=c++11
    
  • 相关阅读:
    mysql 新用户添加和权限
    分治法
    插入排序
    猴子分桃问题
    关于PHP面向对象 静态方法的疑问
    php中static 静态变量和普通变量的区别
    php函数引用返回
    redis 限制请求次数的写法
    cas单点登录认证原理
    聚簇索引和非聚簇索引
  • 原文地址:https://www.cnblogs.com/asuldb/p/12188233.html
Copyright © 2011-2022 走看看