1032 Sharing

1032 Sharing (25 分)

To store English words, one method is to use linked lists and store a word letter by letter. To save some space, we may let the words share the same sublist if they share the same suffix. For example, loading and being are stored as showed in Figure 1.

fig.jpg

Figure 1

You are supposed to find the starting position of the common suffix (e.g. the position of i in Figure 1).

Input Specification:

Each input file contains one test case. For each case, the first line contains two addresses of nodes and a positive N (≤10^​5​​), where the two addresses are the addresses of the first nodes of the two words, and N is the total number of nodes. The address of a node is a 5-digit positive integer, and NULL is represented by −1.

Then N lines follow, each describes a node in the format:

Address Data Next

whereAddress is the position of the node, Data is the letter contained by this node which is an English letter chosen from { a-z, A-Z }, and Next is the position of the next node.

Output Specification:

For each case, simply output the 5-digit starting position of the common suffix. If the two words have no common suffix, output -1 instead.

Sample Input 1:

11111 22222 9
67890 i 00002
00010 a 12345
00003 g -1
12345 D 67890
00002 n 00003
22222 B 23456
11111 L 00001
23456 e 67890
00001 o 00010

Sample Output 1:

67890

Sample Input 2:

00001 00002 4
00001 a 10001
10001 s -1
00002 a 10002
10002 t -1

Sample Output 2:

-1


题型分类:静态链表

题目大意:给出两个单词的开头结点,找出两个单词的公共后缀,找到后输出公共后缀的开始位置,找不到输出-1。

解题思路:用visited来表示结点有没有访问过,第二个单词第一次访问到visited == true的结点时,表示找到公共后缀的起始位置。


#include <cstdio> 

const int maxn = 100010;

typedef struct Node{
	char data;
	int next;
	bool visited;
	Node(){
		visited = false;
	}
}Node;

Node node[maxn];

int main(int argc, char** argv) {
	int word1, word2, N;
	scanf("%d %d %d", &word1, &word2, &N);
	for(int i = 0; i < N; i++){
		int address;
		scanf("%d ", &address);
		scanf("%c %d", &node[address].data, &node[address].next); 
	}
	int p = word1;
	while(p != -1){
		node[p].visited = true;
		p = node[p].next;
	}
	p = word2;
	while(p != -1 && node[p].visited == false){ //找到末尾或者找到相同后缀退出 
		p = node[p].next;
	}
	if(p != -1) printf("%05d", p);
	else printf("-1");
	return 0;
}

 

### False Sharing 的概念 False Sharing 是一种多线程程序中的性能问题,当多个线程访问同一缓存行中的不同数据元素时,即使这些数据逻辑上不相关,由于缓存一致性协议(如 MESI 协议)的机制,仍然会导致缓存行在不同处理器核心之间频繁同步[^1]。这种不必要的缓存一致性操作会显著降低程序的执行效率[^3]。 缓存行是 CPU 缓存的基本单位,其大小通常为 64 字节(在 x86 架构中)。如果两个变量位于同一缓存行内,当一个线程修改其中一个变量时,整个缓存行会被标记为脏数据,其他核心上的缓存副本将失效,从而触发缓存同步操作[^2]。 --- ### 如何优化缓存行以避免 False Sharing 为了减少或避免 False Sharing 的影响,可以采取以下措施: #### 1. 数据对齐 通过确保关键变量在内存中分配到不同的缓存行,可以有效避免 False Sharing。例如,在 Java 中可以使用 `@Contended` 注解(从 Java 8 开始提供),它通过插入填充字节来保证变量之间的缓存行边界。 ```java public class CacheLinePadding { @sun.misc.Contended private long variableA; @sun.misc.Contended private long variableB; } ``` #### 2. 手动填充缓存行 如果不使用内置工具(如 `@Contended`),可以通过手动填充缓存行的方式,确保变量不会共享同一缓存行。例如,在 C++ 中可以使用填充字节数组实现: ```cpp struct CachePaddedStruct { long variableA; char padding[64 - sizeof(long)]; // 填充至缓存行边界 long variableB; char padding2[64 - sizeof(long)]; // 再次填充 }; ``` #### 3. 减少共享变量的访问频率 尽量减少多线程程序中对共享变量的访问频率。可以通过局部变量缓存、分块处理等方式降低对共享资源的竞争[^3]。 #### 4. 使用线程本地存储(Thread-Local Storage, TLS) TLS 可以为每个线程分配独立的存储空间,避免跨线程的数据竞争和缓存行同步问题[^1]。 --- ### 示例代码 以下是一个简单的示例,展示如何通过填充避免 False Sharing: ```java import sun.misc.Contended; public class AvoidFalseSharing { @Contended private volatile long counterA = 0L; @Contended private volatile long counterB = 0L; public static void main(String[] args) throws InterruptedException { AvoidFalseSharing test = new AvoidFalseSharing(); Thread t1 = new Thread(() -> { for (int i = 0; i < 1_000_000; i++) { test.counterA++; } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1_000_000; i++) { test.counterB++; } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("Counter A: " + test.counterA); System.out.println("Counter B: " + test.counterB); } } ``` --- ### 总结 False Sharing 是多线程编程中常见的性能瓶颈,主要由缓存一致性协议引发。通过数据对齐、手动填充缓存行、减少共享变量访问频率以及使用线程本地存储等方法,可以有效缓解或避免这一问题[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值