Subsequence-后继数组+vector

题目描述:

Give a string S and N string Ti, determine whether Ti is a subsequence of S.

If ti is subsequence of S, print YES,else print NO.

If there is an array {K1,K2,K3,⋯ ,Km} so that 1≤K1<K2<K3<⋯<Km≤N and Ski=Ti​, (1≤i≤m), then Ti is a subsequence of S.

输入描述:

The first line is one string S,length(S) ≤100000

The second line is one positive integer N,N≤100000

Then next n lines,every line is a string Ti, length(Ti​) ≤1000

输出描述:

Print N lines. If the i-th Ti is subsequence of S, print YES, else print NO.

输入样例:

abcdefg
3
abc
adg
cba

输出样例:

YES
YES
NO

核心思想:

注意
一、此题目默认字符串只含a~z这26个小写字母!
二、输入只能用scanf,而不能用cin,因为输入太多了,cin会超时!

对于S中的第i个字符,定义它的后继数组是mp[i][26],记录下S[i]后面每个字母首次出现的位置
例如,上面的样例,当i=2时,第2个字母是b。
在第2个字母之后,c首次出现的位置是3,d是4,e是5,f是6,g是7,则 mp[2][‘c’-‘a’]即mp[2][2]的值是3,mp[2][3]=4,mp[2][4]=5,mp[2][5]=6,mp[2][6]=7,mp[2]的其他值赋成0,表示无后继。
在查询时,根据后继层层递进即可。细节见代码。

代码如下:

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1e5+10;//主字符串长度 
const int M=26;//字符种类数,每个字符可能有M个后继 
char ts[N],s[N],ss[N];
int mp[N][M];//例如,mp[6][3]表示,第6个字符后的第一个'd'的位置
int a[M];//每个字母首次出现的位置,即查询时每个字母的入口 
vector<int>vec[M];//vec[i]中存放的是:暂时没有后继'a'+i的字符的位置。
int main()
{
	scanf("%s",ts);
	int len=strlen(ts);
	for(int i=0;i<len;i++)
		s[i+1]=ts[i];
	for(int i=len;i>0;i--)
		a[s[i]-'a']=i;
	for(int i=1;i<=len;i++)
	{
		int w=s[i]-'a';
		int l=vec[w].size();
		if(l)//s[i]能成为 vec[w]中每个元素的后继 
		{
			for(int j=0;j<l;j++)
				mp[vec[w][j]][w]=i;
			vec[w].clear();//注意清空 
		}
		for(int j=0;j<M;j++)//i的26个后继都暂时没有 
			vec[j].push_back(i);
	}
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++)//开始查询 
	{
		scanf("%s",ss);
		int l=strlen(ss);
		int k=a[ss[0]-'a'],j=1;//k!=0,则为后继的位置,k==0则后继无人 
		if(k==0)//连入口都没有,直接NO 
		{
			printf("NO\n");
			continue;
		}
		int flag=1;
		while(1)
		{
			if(j>=l)//直到ss的结束,都一直存在着后继,则ss是S的一个子序列,可以YES 
				break;
			k=mp[k][ss[j]-'a'];
			j++;
			if(k==0)//后继无人,NO 
			{
				flag=0;
				break;
			}
		}
		if(flag)
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;
}

运行结果:

在这里插入图片描述

以下是K-means++多维数据聚类分析的Matlab代码,以及模型性能评估方法: ```matlab % Load data data = load('data.mat'); % Number of clusters to find k = 3; % Initialize centroids using K-means++ centroids = init_centroids(data, k); % Run K-means algorithm for i = 1:100 % Assign each data point to the nearest centroid idx = find_closest_centroids(data, centroids); % Compute new centroids based on the assigned data points centroids = compute_centroids(data, idx, k); end % Plot the clusters plot_clusters(data, idx, k); % Function to initialize centroids using K-means++ function centroids = init_centroids(data, k) % Randomly choose the first centroid centroids = data(randi(size(data, 1)), :); % Choose each subsequent centroid with probability proportional to its % distance from the closest existing centroid for i = 2:k dists = pdist2(data, centroids); [~, D] = min(dists, [], 2); P = min(D, [], 1).^2; P = P / sum(P); centroids(i, :) = data(find(rand < cumsum(P), 1), :); end end % Function to assign each data point to the nearest centroid function idx = find_closest_centroids(data, centroids) dists = pdist2(data, centroids); [~, idx] = min(dists, [], 2); end % Function to compute new centroids based on the assigned data points function centroids = compute_centroids(data, idx, k) for i = 1:k centroids(i, :) = mean(data(idx == i, :), 1); end end % Function to plot the clusters function plot_clusters(data, idx, k) colors = ['r', 'g', 'b', 'y', 'm', 'c']; hold on; for i = 1:k scatter(data(idx == i, 1), data(idx == i, 2), colors(i)); end hold off; end ``` 对于模型性能评估,可以使用以下指标: 1. SSE(Sum of Squared Errors):表示所有数据点到其所属簇心的距离之和,越小越好; 2. Silhouette coefficient:表示聚类结果的紧密度和分离度,范围在-1到1之间,越接近1越好。 可以使用以下代码计算这些指标: ```matlab % SSE dists = pdist2(data, centroids); [~, idx] = min(dists, [], 2); sse = sum(min(dists, [], 2)); % Silhouette coefficient s = silhouette(data, idx); sc = mean(s); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值