An Easy Problem

本文介绍了一种使用单调动态规划(monotonic dynamic programming, DP)和栈(stack)解决特定查询问题的方法。通过定义一个特殊函数f(j),并在给定数组a的情况下进行查询,实现了高效的查询响应。文章还提供了一个具体的实现示例,包括输入输出格式、样例及其解释。

Description

  Now we define that:

  A(j)={i|0<i<j&&a[i]<a[j]}

  Here a is an array with n element(1<=n<=1000000);

  And then we define a function f that:

  int f(int j){

      if(A(j) is not empty) return max( A(j) );

      else return -1;

  }

Input

  The first line contain an integer n(1<=n<=1000000),the size of the array a.

  The second line contain n integers describe the array a.

  The third line is an integer m(1<=m<=1000000),the number of the query.

  And then follow m lines,each line is an integer j(1<=j<=n).

Output

  For each query j,output a[f(j)] if f(j)>=1,Otherwise output -1 instead.

Sample Input

  3

  1 2 3

  3

  1

  2

  3

Sample Output

  -1

  1

  2





单调DP,用另一数组记录下a[f(i)],可用stack实现。

#include<iostream>
#include<stack>
#include<cstdio>
using namespace std;
#define N 1000005
int a[N],b[N];
int main()
{
	int n,m,i,temp,x;
	stack<int> S;
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
		if(S.empty())
		{
			b[i]=-1;
			S.push(a[i]);
		}
		else
		{
			temp=S.top();
			if(temp<a[i])
			{
				b[i]=temp;
				S.push(a[i]);
			}
			else
			{
				S.pop();
				while(!S.empty())
				{
					temp=S.top();
					if(temp<a[i])
					{
						b[i]=temp;
						S.push(a[i]);
						break;
					}
					else
						S.pop();
				}
				if(S.empty())
				{
					b[i]=-1;
					S.push(a[i]);
				}
			}
		}
	}
	scanf("%d",&m);
	while(m--)
	{
		scanf("%d",&x);
		printf("%d\n",b[x-1]);
	}
	return 0;
}




<think>我们有一个字符串`sentence`,其中包含用空格分隔的单词,以及一个字符串`searchWord`。 我们需要检查`searchWord`是否是`sentence`中任意单词的前缀(即单词的前导连续子字符串)。 如果是,返回第一个匹配的单词在句子中的下标(从1开始)。 如果是多个单词的前缀,返回最小的下标。 如果没有匹配,返回-1。 步骤: 1. 将句子`sentence`按空格分割成单词列表。 2. 遍历这个单词列表(同时记录下标,从0开始,但返回时需要+1)。 3. 对于每个单词,检查`searchWord`是否是该单词的前缀。 注意:我们可以使用字符串的`startswith`方法,或者比较单词的前缀子串(长度等于`searchWord`)是否等于`searchWord`。 4. 一旦找到第一个匹配的单词,就返回当前下标+1(因为题目要求下标从1开始)。 5. 如果遍历完都没有找到,则返回-1。 注意:题目要求是前缀,即必须是单词开头的一部分,所以直接可以用`startswith`方法。 我们使用Python来实现这个函数。 函数定义: def is_prefix_of_word(sentence: str, searchWord: str) -> int: 示例: 输入:sentence = "i love eating burger", searchWord = "burg" 输出:4 因为"burg"是"burger"的前缀,而"burger"是第4个单词(下标从1开始) 边界情况: - 如果句子为空,或者searchWord为空,应该返回-1?(题目未明确说明,但searchWord为空字符串时,任何单词都以其开头?但题目说“前导连续子字符串”,空字符串是任何字符串的前缀) 但是题目要求:如果searchWord不是任何单词的前缀,返回-1。所以空字符串也是前缀?但题目中检索词可能不为空。根据题目要求,我们按照实现。 然而,题目描述中并没有提到空字符串的情况,但按照定义,空字符串是任意字符串的前缀。所以如果searchWord为空,那么第一个单词(下标1)就应该匹配。 但题目中指定了检索词searchWord,我们假设它非空?但是题目没有明确排除空字符串。因此,我们需要考虑这种情况。 但是引用[2]中说明:字符串 S 的 「前缀」是 S 的任何前导连续子字符串。那么空字符串也是前缀。 然而,题目要求中:如果searchWord是多个单词的前缀,则返回第一个。所以如果searchWord为空,则所有的单词都满足,那么返回第一个单词的下标1。 为了避免问题,我们按照以下逻辑: - 如果searchWord为空,那么我们可以返回1(因为空字符串是每个单词的前缀,第一个单词就满足)。 - 但是,题目可能不会输入空字符串,但为了健壮性,我们可以考虑。 不过,题目描述中并没有说searchWord非空,所以我们需要处理。 因此,我们可以在函数开始时判断:如果searchWord为空,则返回1(如果句子至少有一个单词)?但句子可能为空(没有单词)。所以: 如果句子为空,则返回-1(因为没有任何单词)。 如果句子非空,且searchWord为空,则返回1。 但是,我们也可以这样处理:在遍历单词时,如果遇到空单词(比如句子中有连续空格?),但我们按空格分割,连续空格会分割出空字符串吗? 题目说:句子由若干用单个空格分隔的单词组成。所以不会有连续空格,也不会有空单词。 因此,假设输入是规范的:单词之间用单个空格分隔,首尾没有空格?不一定,但分割函数会处理首尾空格(split默认会去除首尾空格,并分割中间连续空格?但题目说单个空格,所以按空格分割即可)。 具体步骤: 1. 使用split()将句子分割成单词列表(默认按空格分割,连续空格会被分割成空字符串?但是题目是单个空格分隔,所以不会出现连续空格,因此split()和split(' ')都可以,但split()会忽略前导和尾随空格以及连续空格,而split(' ')会保留空字符串。根据题目,我们使用split()即可,因为题目是单个空格分隔,所以split()会正确分割。 2. 遍历单词列表,索引从0开始。 3. 对于每个单词,检查是否以searchWord开头。 4. 如果是,返回当前索引+1。 5. 遍历结束,返回-1。 但是,考虑searchWord长度可能大于单词长度?例如单词是"a",而searchWord是"ab",那么"a"不是"ab"的前缀,而且"ab"也不是"a"的前缀(因为"a"的长度小于"ab",所以"a"不可能包含"ab"作为前缀)。所以如果单词长度小于searchWord的长度,肯定不匹配,我们可以跳过。 我们可以先检查当前单词的长度是否大于等于searchWord的长度,然后再检查前缀。或者直接使用startswith,因为startswith会自动处理(如果单词长度小于searchWord,startswith会返回False)。 所以直接用startswith即可。 代码实现: 注意:如果searchWord为空字符串,那么任何单词都会满足,因为每个单词都以空字符串开头。所以我们需要在循环前判断空字符串的情况。 因此,我们先处理空字符串的情况: if searchWord == "": return 1 # 因为第一个单词一定满足 但是,如果句子为空呢?句子为空,split得到空列表,那么我们应该返回-1。所以: if searchWord == "": if sentence.strip() == "": # 其实可以直接判断split后的列表是否为空 return -1 else: return 1 但是我们可以这样处理:如果searchWord为空,那么第一个单词(如果存在)就满足。所以: words = sentence.split() if not words: # 句子分割后没有单词 return -1 if searchWord == "": return 1 然后遍历words。 但是题目要求:如果searchWord是多个单词的前缀,返回第一个匹配的下标。所以空字符串时,我们返回第一个单词的下标1,这是正确的。 因此代码如下: </think>以下是实现检查检索词是否为句子中任意单词前缀并返回对应单词下标的程序代码(Python实现): ```python def is_prefix_of_word(sentence: str, searchWord: str) -> int: words = sentence.split() # 将句子分割为单词列表 for i, word in enumerate(words): # 检查当前单词是否以检索词开头 if word.startswith(searchWord): return i + 1 # 返回下标(从1开始计数) return -1 # 无匹配时返回-1 ``` ### 代码说明: 1. **分割句子**:使用`.split()`将句子按空格分割成单词列表 (示例:`"i love coding"` → `["i", "love", "coding"]`) 2. **遍历检查**:对每个单词检查是否以`searchWord`开头 - 使用`.startswith()`方法进行前缀匹配 - 匹配成功立即返回**下标+1**(题目要求下标从1开始) 3. **边界处理**: - 空检索词:默认匹配所有单词(返回第一个单词下标1) - 无匹配:遍历结束后返回-1 ### 示例测试: ```python print(is_prefix_of_word("i love programming", "prog")) # 输出:3 print(is_prefix_of_word("hello world", "wor")) # 输出:2 print(is_prefix_of_word("python is fun", "java")) # 输出:-1 ``` ### 时间复杂度: - $O(N \times K)$,其中: - $N$ 是句子中单词数量 - $K$ 是检索词长度 (只需一次遍历,高效处理大文本场景)[^1][^2]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值