CF149E题解

CF149E题解—KMP算法

题意

给出一个长字符串S和一组询问字符串P,对于每个询问需要知道在S中是否存在两个位置不同的子串可以组成该询问字符串。

分析:
运用KMP算法对正串S和P进行匹配,用数组lo[x]记录第一次(第一次很关键)匹配的长度为x时其匹配在S中的末位置,再将S和P逆置,运用KMP算法再进行匹配,对于每一次匹配长度为x,查找对应剩下的长度m-x(m为P串长)是否已经存在,再加判断位置是否越界即可。

我的代码


#include<iostream>
#include<string>
#include<algorithm>
#include<string.h>
#define N 1005
using namespace std;
int dp[N],lo[N];
void getdp(string s){			//求next数组 
	memset(dp,0,sizeof(dp));
	dp[0]=-1;
	int len=s.length(),k=-1,j=0;
	while(j<len){
		if(k==-1||s[k]==s[j]){
			k++;j++;
			dp[j]=k;
		}
		else{
			k=dp[k];
		} 
	}
}
int kmp(string t,string p,int judge){
	int i=0,j=0,n=t.length(),m=p.length();
	int maxj=-1;
	getdp(p);
	while(i<n&&j<m){
		if(j==-1||t[i]==p[j]){
			i++;j++;
		}
		else{
			j=dp[j];
		}
		if(judge==1&&j!=-1&&j!=0&&!lo[j])	//匹配正串记录第一次匹配长度为j时在样本串中的位置 
			lo[j]=i;
		if(judge==2&&j!=-1&&j!=0&&lo[m-j]&&n-i+1>lo[m-j])	//匹配逆置的模式串是否成功 
			return 1;
	}
	return 0;
}
int main(){
	string t,p,temp;
	int nu,ans=0;
	cin>>t>>nu;
	if(t.length()==1){					//样本串长度为1是直接输出答案 
		cout<<"0"<<endl;
		return 0;
	}
	temp.assign(t.rbegin(),t.rend());	//逆置样本串 
	while(nu--){
		memset(lo,0,sizeof(lo));
		cin>>p;
		kmp(t,p,1);						//匹配正串 
		reverse(p.begin(),p.end());
		if(kmp(temp,p,2))				//匹配逆置的模式串 
			ans++;
	}
	cout<<ans<<endl;
} 
CF Directional Increase是一道经典的算法题目,通常出现在编程竞赛中。题目要求在一个二维网格中,找到从起点到终点的路径,使得路径上的数值递增。以下是详细的题解: ### 题目描述 给定一个二维网格,每个格子中有一个整数。起点在左上角,终点在右下角。你可以从当前格子移动到右边的格子或下边的格子。找到一条路径,使得路径上的数值递增。 ### 解题思路 1. **动态规划**:使用动态规划来解决问题。定义一个二维数组`dp[i][j]`,表示从起点到格子`(i, j)`的递增路径的长度。 2. **初始化**:起点`dp[0][0]`的值为`grid[0][0]`。 3. **状态转移方程**: - 如果从上方移动到当前格子`(i, j)`,则`dp[i][j] = max(dp[i][j], dp[i-1][j] + 1)`,前提是`grid[i][j] > grid[i-1][j]`。 - 如果从左方移动到当前格子`(i, j)`,则`dp[i][j] = max(dp[i][j], dp[i][j-1] + 1)`,前提是`grid[i][j] > grid[i][j-1]`。 ### 代码实现 ```python def directional_increase(grid): if not grid or not grid[0]: return 0 m, n = len(grid), len(grid[0]) dp = [[1] * n for _ in range(m)] for i in range(m): for j in range(n): if i > 0 and grid[i][j] > grid[i-1][j]: dp[i][j] = max(dp[i][j], dp[i-1][j] + 1) if j > 0 and grid[i][j] > grid[i][j-1]: dp[i][j] = max(dp[i][j], dp[i][j-1] + 1) return dp[m-1][n-1] # 示例 grid = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] print(directional_increase(grid)) # 输出: 5 ``` ### 解释 - 初始化`dp`数组为全1,因为每个格子的递增路径至少为1。 - 遍历每个格子,更新`dp[i][j]`的值。 - 最后,`dp[m-1][n-1]`即为从起点到终点的递增路径的最大长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值