【扩展kmp+优先队列(结构体)排序】匹配格式

大致思路

耶这道我自己比较顺利地做出来了。

为什么联想到要用拓展kmp呢?其实你看看,首先是有“头尾匹配”的,只不过花样多了点。

这道题我是通过getnext()先把所有next值得到。需要注意“不重复”的题意要求,所以自己由此加了些限制条件:

nextt[i]+1<=i   //中间部分与头不重复
n-q.top().len+1>q.top().i+q.top().len-1     //中间部分与尾不重复

然后一个优化是“从大到小枚举”,首先这个长度肯定是要小于等于n/3的,而且我要找最大,所以从大到小开始枚举,符合条件就立马结束程序即可。所以这里用到“优先队列”,想让其以长度从大到小排序。这里优先队列的元素是结构体,自己赶紧去温习了一下之前写的博客,原来对于这种情况,是让结构体定义中多加一个bool operator<函数,然后男左女右女士优先原则。

自己觉得!!真的这种题,干瞪眼在那里想真的不如拿起笔写几个例子!!其实写例子分析其中关系就是在转化为数学思维考虑了!!对于写程序给思路和全面考虑情况很有帮助。以后没思路就多写例子吧。


AC代码

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#include<queue>
const int maxn=1e6+5;
int nextt[maxn];
int n;
char t[maxn];
void getnext()
{
	nextt[1]=n;
	int a=0;
	for(int i=1;t[i]==t[i+1];i++) a++;
	nextt[2]=a;
	int k=2,p,l;
	for(int i=3;i<=n;i++)
	{
		p=k+nextt[k]-1;
		l=nextt[i-k+1];
		if(p-i>=l) nextt[i]=l;
		else
		{
			int j=p-i+1;
			if(j<0) j=0;
			while(i+j<=n && t[1+j]==t[i+j]) j++;
			nextt[i]=j;
		}
		k=i;
	}
}
struct node
{
	int i;int len;
	bool operator < (const node &a) const
	{
		return len<a.len || (len==a.len && i>a.i);
	}	
	node(int ii,int ll)
	{
		i=ii;
		len=ll;
	}	
};
priority_queue<node> q;
int main()
{
	scanf("%s",t+1);
	n=strlen(t+1);
	getnext();
	for(int i=1;i<=n;i++)
	{
		if(nextt[i]!=0 && nextt[i]<=n/3 && nextt[i]+1<=i)
		{
		//	cout<<i<<" "<<nextt[i]<<endl;
			q.push(node(i,nextt[i]));
		}
	}
	while(q.empty()==false)
	{
	//	cout<<"!"<<q.top().i<<" "<<q.top().len<<endl;
		if(nextt[n-q.top().len+1]==q.top().len)
		{
			if(n-q.top().len+1>q.top().i+q.top().len-1)
			{
				cout<<q.top().len;
				return 0;
			}
		}
		q.pop();
	}
	return 0;
}
刚开始因为没在主函数里调用getnext() 调试了两三次.....别再这样了拜托T T.....


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值