您的位置:首页 > 其它

查找包含特定字符最短片段

2016-06-18 11:34 246 查看
       原地址(表示一下对原作者的敬意,哈哈):查找包含特定字符最短片段 -- 修江的芦苇

        csdn不允许回复里加那么多代码,只有把这个网址写回去咯~

这里,再重新说一下题的意思:

        原文如下:

                   找出一个字符串包含的特定的字符最短的片段,例如abcccda,包含bd,那么最短的是bcccd(实际原题是单词,每个词就像一个字符)

        解释一下:

               对特定字符没有顺序要求,比如包含acd,那么该题的结果是cda(最后3个)。

        小生只在此说一下自己的思路咯:

               维护一个双向链表,每次找到特定字符就把该节点置于链表的末尾,当链表的长度达到特定字符的个数时,就表示有结果了。如果链表结尾的位置减去链表头部的位置+1等于了特定字符的个数时,则产生最优解了。

        如何验证结果的正确性呢?

        假设,原字符串中有很多重复的,如 aaaaaabbbbbcccccccccdddddaaaabdccdcbc,包含bd,最短的怎么找呢?当找到一个b时,并没有结果,那么这时候,我选择哪个b呢?很明显,越靠后的,产生的结果才会更优(贪心一下咯~),那就选择最后一个b。当d出现时,bd都已经存在了:"bcccccccccd",那么就已经产生出一个结果了,这个结果是不是最优呢?看最后一个b和第一个d之间的距离,明显大于2,很好,继续往后找。再后面再找的过程中,很碰到一个d就会出现一个结果,但结果比之前的要差,抛弃不要。经过一串a我们又发现了一个b,哈,这个时候的子串"daaaab"长度比之前要小,那么它就是至今为止的最优解了。但很不幸的是紧跟其后的有一个d,那这个时候的子串"bd",刚好是特定字符的个数,还用往后找吗?不需要了,已经找到了。

        好了,臭屁到此为止。Talk is cheap, show me the code:

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

int main() {
char* s = "abcccda";
char* t = "bd";
int t_len;

char is_given[128];
memset(is_given, 0, sizeof(is_given));
for (t_len = 0; t[t_len]; t_len++) {
is_given[t[t_len]] = 1;
}

char prev[128], next[128], head, end;
int pos[128], cnt;
memset(prev, -1, sizeof(prev));
memset(next, -1, sizeof(next));
memset(pos, -1, sizeof(pos));
head = end = 0;
cnt = 0;

int left = 0, right = 1 << 30;

int i;
for (i = 0; s[i]; i++) {
if (!is_given[s[i]]) {
continue;
}

pos[s[i]] = i;
if (s[i] == head) {
if (head != end) {
head = next[head];
prev[next[s[i]]] = -1;
next[s[i]] = -1;
next[end] = s[i];
end = s[i];
}
} else if (s[i] == end) {
// pass
} else {
if (head) {
if (prev[s[i]] == -1 && next[s[i]] == -1) {
next[end] = s[i];
prev[s[i]] = end;
end = s[i];
cnt++;
} else {
next[prev[s[i]]] = next[s[i]];
prev[next[s[i]]] = prev[s[i]];
next[end] = s[i];
prev[s[i]] = end;
end = s[i];
}
} else {
head = end = s[i];
cnt++;
}
}

if (cnt == t_len && pos[end]-pos[head]<right-left) {
left = pos[head];
right = pos[end];
if (right-left+1 == t_len) {
break;
}
}
}

if (cnt != t_len) {
printf("Not found!\n");
} else {
printf("s[%d:%d]\n", left, right+1);
for (i = left; i <= right; i++) {
printf("%c", s[i]);
}
printf("\n");
}

return 0;
}

         运行结果:

         s[1:6]

         bcccd
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  字符串 链表 哈希