【问题标题】:Appearance of characters in substrings子字符串中字符的外观
【发布时间】:2019-02-06 01:25:38
【问题描述】:

给定一个 S 字符串,如果字符 C 出现在 S 的从位置 I 开始并且长度为 T 的子字符串中,则编写一个正确响应的程序。

条目
由字母数字字符组成的 S 字符串,长度最多为 1,000,000。随后是一个整数 N,后跟 N 个三元组 C、I、T。您可以假设 1≤N≤10,000 即 0≤I

退出
对于每个问题,如果字符出现在指定的子字符串中,则为 1,否则为 0。

我的想法是实现二分搜索,但合格的法官说它超出了预期的时间,我不知道如何将其优化到法官接受我的算法的程度。例如,一个条目可以是:

how are you
3
h 0 3
1
o 2 5
1
a 4 4
0 

我的代码:

#include <stdio.h>
#include <string.h>

int busqcadena(char cadena[], int a[],char x,int pos,int n);

int main()
{
    char cadena[1000000]; 
    char c;
    int t = 0, i; 
    int pos, lon, a[1000000], j = 0;
    do{
        fflush(stdin);
        c = getchar();
        cadena[i++] = c;
        a[j] = j;
        j++;
    } while (c != '\n');
    cadena[ i - 1 ] = '\0'; 

    scanf("%d",&t);
    for( int k = 0; k < t; k++){
    char pa; pos = 0; lon = 0;
    scanf("%s %d %d",&pa, &pos, &lon);
    int busq3 = busqcadena(cadena,a,pa,pos,lon);
    if( busq3 != -1){
        printf("1\n");
    }else{
        printf("0\n");
    } 
}
    return 0; 
}

int busqcadena(char cadena[], int arr[],char x,int pos,int n){
    int a = 0, b = n - 1;
    while( a <= b ){
        int k = (a+b)/2;
        if( cadena[k] == x && arr[k] == pos){
            return arr[k]; 
        }
        if( arr[k] > pos ) b = k - 1;
        else a = k + 1;
    }
    return -1;
}

【问题讨论】:

  • 您使用的是 C 还是 C++?选择一个并适当调整标签。
  • 我在代码中使用 C

标签: c algorithm binary-search binary-data


【解决方案1】:

由于您只有固定数量的字符,您可以从索引0 开始计算每个字符的计数。一旦你这样做了,你只需要检查该字符的计数是否从I增加到T。伪代码如下

char_count = 26 # I am assuming only lower case letter, but change it if its not
max_len = 1000000  # maximum length of string
count = int[char_count][max_len]  # 2D array storing cumulative count for each character, fill with 0

# read the string s
# populate the count array
count[s[0]][0] = 1  # set count 1 for first character in S
for i=0:char_count:
    for j=1:len(s):
        if s[j] == char[i]:  # equals i-th character
            count[i][j] = count[i][j-1]+1
        else:
            count[i][j] = count[i][j-1]

# for each query do following 
for q=0:num_queries:
    if count[C][T] != count[C][I]:
        print(1)
    else:
        print(0)

【讨论】:

  • 可以通过将count 声明为int[max_len][char_count] 来优化初始化,删除for i=0:char_count: 循环,然后只遍历字符串,首先使用memcpy() 将前一列复制到当前,然后在当前列的适当行中添加一个。
  • 它仍然需要复制最后一列。但实际上它应该更快。
  • 这需要一个包含 2600 万个条目的数组(实际上是 3600 万,因为 OP 说字母数字,如果输入区分大小写,可能是 6200 万。)对于堆栈分配来说,这几乎肯定太大了,所以 malloc 将是需要。 (我知道这是伪代码,但警告似乎是相关的。)
猜你喜欢
  • 1970-01-01
  • 2020-02-11
  • 1970-01-01
  • 2014-09-21
  • 1970-01-01
  • 2019-01-03
  • 2014-08-30
  • 1970-01-01
相关资源
最近更新 更多