首页 > 其他分享 >[SCOI2003]字符串折叠

[SCOI2003]字符串折叠

时间:2022-08-14 23:35:24浏览次数:74  
标签:ch 折叠 long 枚举 循环 字符串 长度 SCOI2003

题目链接

Solution

这种字符串题一般都是区间 dp,设 \(f(i,j)\) 表示第 \(i\) 到 \(j\) 的子串的最小长度,如果没有折叠操作,则枚举断点 \(k\),转移方程为:

\[f(i,j)=\min(f(i,j),f(i,k)+f(k+1,j)) \]

若有折叠操作,这时想要折叠就必须满足整段是一个循环,所以我们枚举循环节长度,用 hash 判断是否是循环节,若是,则转移方程如下:

\[f(i,j)=\min(f(i,j),f(i,k)+2+t(len/l)) \]

其中加 \(2\) 表示括号,\(len\) 是我们枚举的子串长度,\(l\) 是循环节长度,\(t\) 数组表示某个整数占的位数。

补充

hash 判循环节的方式如下:
image
如图,\(l\) 是我们枚举的循环节长度,蓝色线段是我们需要判断的,黄色部分的长度为 \(l\),若蓝色线段的 hash 值相等,则有 ① 等于 ③,而 ③ 又等于 ②,像这样就可以像推多米诺骨牌一样把后面的全部判断成相等,即可判断循环节。
此算法判断一个段是否为循环节是 \(O(1)\) 的,非常高效。

Code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
using namespace std;
void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
const int N=107,K=133;
char c[N];
int f[N][N],t[N];
ull g[N],p[N];
void init()
{
	p[0]=1;
	for(int i=1;i<=105;i++)
		p[i]=p[i-1]*K;
}
void Get(char *s,int n)
{
	for(int i=1;i<=n;i++)
		g[i]=g[i-1]*K+s[i];
}
int gethash(int l,int r)
{return g[r]-g[l-1]*p[r-l+1];}
main()
{
	scanf("%s",c+1);
	int n=strlen(c+1);
	init();Get(c,n);
	memset(f,63,sizeof f);
	for(int i=1;i<=9;i++)t[i]=1;
	for(int i=10;i<=99;i++)t[i]=2;
	t[100]=3;
	for(int i=1;i<=n;i++)f[i][i]=1;
	for(int len=2;len<=n;len++)
	for(int i=1;i<=n-len+1;i++)
	{
		int j=i+len-1;
		for(int k=i;k<j;k++)
			f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
		for(int k=i;k<j;k++)
		{
			int l=k-i+1;
			if(len%l!=0)continue;
			if(gethash(i,j-l)==gethash(i+l,j))
				f[i][j]=min(f[i][j],f[i][k]+2+t[len/l]);
		}
	}
	cout<<f[1][n];
	return 0;
}

标签:ch,折叠,long,枚举,循环,字符串,长度,SCOI2003
From: https://www.cnblogs.com/LAK666/p/16586676.html

相关文章

  • 字符串p型编码
    题目描述给定一个完全由数字字符(‘0’,‘1’,‘2’,…,‘9’)构成的字符串str,请写出str的p型编码串。例如:字符串122344111可被描述为"1个1、2个2、1个3、2个4、3个1",因此......
  • 字符串
    字符串字符串概述字符串是一个数据结构(串),将同样的内容串在一起,因为在对应的js里面字符串是属于一个值类型(值类型是常量常量是不能变的)字符串是不能改变的。作为存储结......
  • 字符串的常用操作
    (一)字符串的查询index()查找子串substr第一次出现的位置,如果查找的字串不存在时,则抛出ValueErrorrindex()查找子串substr最后一次出现的位置,如果查找的字串不存在时,则抛......
  • python 中字符串 内置函数 find
     001、>>>str1="xabdxyabxykk"##测试字符串>>>str1'xabdxyabxykk'>>>str1.find("ab")##返回测试字符串中首次匹配ab的首字符的索......
  • python 中字符串拆分可直接赋值给变量名(列表中的元素可以直接赋值给变量)
     001、>>>test1="100200"##test1为字符串>>>test1'100200'>>>a,b=test1.split()##拆分字符串,直接赋值给变量名>>>a'100'>>>b'200'......
  • python 中字符串格式化函数 format()
     001、>>>"{0}".format("xxx")##位置参数'xxx'>>>"{0}.{1}.{2}".format("xxx","yyy","zzz")'xxx.yyy.zzz'>>>"\t{0}.{......
  • leetcode438_找到字符串中所有字母异位词
    438.找到字符串中所有字母异位词方法一:简单滑动窗口满足异位词条件:(1)s中子串s'与目标字符串p的长度相等(2)s'与p中字母相同(对排列方式没有要求)算法思路:在字符串s中构......
  • 并查集(字符串形式)
    链接classSolution{//使用Map来保存每个节点的父节点Map<String,String>par=newHashMap<>();publicString[]trulyMostPopular(String[]nam......
  • String.valueOf 出来的值为null,null为一个字符串
    id为null时候,这个null为一个字符串,当用  StringUtils.isBlank判断时候会出现false  改用 ......
  • Incorrect string value EFCore使用MySQL数据库GUID类型的字符串映射问题
    1.MySQL中需要存储36位GUID,EFCore字段映射位GUID类型,EFCore添加的时候报错:Incorrectstringvalue2.第一种解决方式:设置GUID字符集publicclassBizReviewEntityConfigu......