CF 835D D. Palindromic characteristics 字符串hash

本文介绍了一种通过暴力记忆化搜索算法解决K回文字符串计数问题的方法,利用Hash技巧来快速判断字符串是否为回文及计算不同级别的K回文串数量。

题意。 定义k回文,一个是k回文的串

那么他本身是回文,并且左右相等,并且左右是k-1回文

问:一个S,所以字串分别是x回文?输出1----n回文的数目

思路:

直接暴力记忆化搜索!枚举判断就好了,回文和相等的条件都用hash判断就好了,注意下标问题!!!!尤其是回文时候的下标问题!!!


代码:

#include<bits/stdc++.h>
using namespace std;
#define MEM(a,b) memset(a,b,sizeof(a))
#define PB push_back
#define MP make_pair
#define X first
#define Y second
#define bug puts("bug");
typedef long long ll;
typedef pair<ll,ll> pii;
const double PI=acos(-1);
const int maxn=1e6+10;
int n;
string s;
int dp[5005][5005],ans[maxn],vis[5005][5005];
const int MAXN = 50100;
const unsigned long long SEED = 13331;
unsigned long long P[MAXN],S[MAXN],RS[MAXN];
unsigned long long HS(int l,int r){
    if(l==r) return s[l];
    ++l;++r;
    return S[r] - S[l-1]*P[r-l+1];
}
unsigned long long RHS(int l,int r){
    if(l==r) return s[l];
    l=n-l-1,r=n-r-1;swap(l,r);
    ++l;++r;
    return RS[r] - RS[l-1]*P[r-l+1];
}
void DFS(int l,int r){
    if(vis[l][r]) return;
    vis[l][r]=1;
    if(l==r){
        dp[l][r]=1;
        return;
    }
    int rr=(l+r-1)/2,ll=(l+r)/2+1;
    if(RHS(l,rr)==HS(ll,r)) dp[l][r]=1;
    DFS(l,rr);DFS(ll,r);
    if(dp[l][r]&&HS(l,rr)==HS(ll,r))
        dp[l][r]=min(dp[ll][r],dp[l][rr])+1;
}

int main(){
    P[0] = 1;
    for(int i = 1; i < MAXN; i++)P[i] = P[i-1] * SEED;
    cin>>s;
    MEM(vis,0);MEM(dp,0);MEM(ans,0);
    n=s.size();
    RS[0]=S[0] = 0;
    for(int i = 1; i <= n; i++)S[i] = S[i-1]*SEED + s[i-1];
    for(int i = 1; i <= n; i++)RS[i] = RS[i-1]*SEED + s[n-i];
    for(int i=0;i<n;i++)
        for(int j=i;j<n;j++)DFS(i,j);
    for(int i=0;i<n;i++)
        for(int j=i;j<n;j++)ans[dp[i][j]]++;
    for(int i=n-1;i>=1;i--) ans[i]+=ans[i+1];
    for(int i=1;i<=n;i++)
        printf("%d%c",ans[i]," \n"[i==n]);
    return 0;
}


转载于:https://www.cnblogs.com/zhangxianlong/p/10672510.html

### 如何生成回文字符串 生成回文字符串的核心在于理解其结构特点:回文字符串是从左到右和从右到左完全相同的序列。以下是几种常见编程语言中的实现方式。 #### C语言实现 在C语言中,可以先创建一个基础字符串,再将其反转并拼接到原字符串之后形成完整的回文字符串。 ```c #include <stdio.h> #include <string.h> void generatePalindrome(char *input, char result[]) { int len = strlen(input); strcpy(result, input); // 将原始字符串复制到结果数组中 for(int i=len-1; i>=0; --i){ result[len+len-1-i] = input[i]; // 反转部分追加到后面 } } int main(){ char original[50], palindromeResult[100]; printf("请输入一个字符串:"); scanf("%s",original); generatePalindrome(original,palindromeResult); printf("生成的回文字符串:%s\n",palindromeResult); } ``` 此代码通过`generatePalindrome`函数接受任意输入字符串,并返回对应的完整回文形式[^1]. #### Python 实现 Python 提供了简洁的方式来处理字符串操作,利用切片功能能够轻松完成任务。 ```python def create_palindrome(s): return s + s[::-1] if __name__ == "__main__": user_input = input('Enter a string:') palindromic_string = create_palindrome(user_input) print(f'Generated Palindrome:{palindromic_string}') ``` 这里定义了一个名为 `create_palindrome` 的辅助函数用于构建给定参数的镜像副本[^2]. #### Java 实现 Java 中同样也可以借助 StringBuilder 类提供的 reverse 方法快速达成目标. ```java import java.util.Scanner; public class Main{ public static String makePalindrome(String baseStr){ StringBuilder sb=new StringBuilder(baseStr).reverse(); return new StringBuilder().append(baseStr).append(sb.toString()).toString(); } public static void main(String[] args)throws Exception{ Scanner sc=new Scanner(System.in); System.out.println("Please enter your text here:"); String raw=sc.nextLine(); String finalPalin=makePalindrome(raw); System.out.printf("Your generated palindrome is %s ",finalPalin ); } } ``` 以上三种不同风格的语言版本均实现了基本需求——基于用户提供的一半内容自动生成另一半构成整个回文体.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值